From 24d9521c7ae72e146025f10ea85b07ebd7041716 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 11 Dec 2006 09:34:50 -0800 Subject: [PATCH 01/32] Add error messages for previous silent DRI initialization failures. --- src/i830_dri.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/i830_dri.c b/src/i830_dri.c index b3206336..0f6145b2 100644 --- a/src/i830_dri.c +++ b/src/i830_dri.c @@ -426,15 +426,24 @@ I830CheckDRIAvailable(ScrnInfoPtr pScrn) /* Check that the GLX, DRI, and DRM modules have been loaded by testing * for known symbols in each module. */ - if (!xf86LoaderCheckSymbol("GlxSetVisualConfigs")) + if (!xf86LoaderCheckSymbol("GlxSetVisualConfigs")) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[dri] %s failed: glx not loaded\n", __FUNCTION__); return FALSE; - if (!xf86LoaderCheckSymbol("DRIScreenInit")) + } + if (!xf86LoaderCheckSymbol("DRIScreenInit")) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[dri] %s failed: dri not loaded\n", __FUNCTION__); return FALSE; - if (!xf86LoaderCheckSymbol("drmAvailable")) + } + if (!xf86LoaderCheckSymbol("drmAvailable")) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[dri] %s failed: libdrm not loaded\n", __FUNCTION__); return FALSE; + } if (!xf86LoaderCheckSymbol("DRIQueryVersion")) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "[dri] %s failed (libdri.a too old)\n", "I830CheckDRIAvailable"); + "[dri] %s failed (libdri.a too old)\n", __FUNCTION__); return FALSE; } From b3865f34669319f449f2da8f87a4eef6ec8e7804 Mon Sep 17 00:00:00 2001 From: "Joshua J. Berry" Date: Mon, 11 Dec 2006 14:46:20 -0800 Subject: [PATCH 02/32] Include i830.h to get M_T_* compat defines for older X Servers. Not duplicating the defines ensures that we won't let the compat bits slip into the X Server when we move this code over there. --- src/i830_xf86Crtc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c index 3a592e50..448d4f94 100644 --- a/src/i830_xf86Crtc.c +++ b/src/i830_xf86Crtc.c @@ -32,6 +32,7 @@ #include "xf86.h" #include "xf86DDC.h" +#include "i830.h" #include "i830_xf86Crtc.h" #include "X11/extensions/render.h" From c21baa5a3044eb66f2518b018dae07eadb989aa1 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 11 Dec 2006 15:15:01 -0800 Subject: [PATCH 03/32] Remove dead remnants of old clone mode support. --- src/i830.h | 5 ----- src/i830_display.c | 10 ---------- src/i830_driver.c | 27 --------------------------- src/i830_video.c | 14 +------------- 4 files changed, 1 insertion(+), 55 deletions(-) diff --git a/src/i830.h b/src/i830.h index ce9b4614..2a7a1d88 100644 --- a/src/i830.h +++ b/src/i830.h @@ -247,11 +247,6 @@ typedef struct _I830Rec { */ DisplayModePtr savedCurrentMode; - Bool Clone; - int CloneRefresh; - int CloneHDisplay; - int CloneVDisplay; - I830EntPtr entityPrivate; int init; diff --git a/src/i830_display.c b/src/i830_display.c index 439c2986..6206243e 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -983,16 +983,6 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) xfree(pI830->savedCurrentMode->name); xfree(pI830->savedCurrentMode); pI830->savedCurrentMode = NULL; - - /* If we might have enabled/disabled some pipes, we need to reset - * cloning mode support. - */ - if (pI830->xf86_config.num_crtc >= 2 && - pI830->xf86_config.crtc[0]->enabled && - pI830->xf86_config.crtc[1]->enabled) - pI830->Clone = TRUE; - else - pI830->Clone = FALSE; /* If HW cursor currently showing, reset cursor state */ if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) diff --git a/src/i830_driver.c b/src/i830_driver.c index 61ce8add..19f94260 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -274,8 +274,6 @@ typedef enum { OPTION_DISPLAY_INFO, OPTION_DEVICE_PRESENCE, OPTION_MONITOR_LAYOUT, - OPTION_CLONE, - OPTION_CLONE_REFRESH, OPTION_CHECKDEVICES, OPTION_FIXEDPIPE, OPTION_ROTATE, @@ -297,8 +295,6 @@ static OptionInfoRec I830Options[] = { {OPTION_COLOR_KEY, "ColorKey", OPTV_INTEGER, {0}, FALSE}, {OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE}, {OPTION_MONITOR_LAYOUT, "MonitorLayout", OPTV_ANYSTR,{0}, FALSE}, - {OPTION_CLONE, "Clone", OPTV_BOOLEAN, {0}, FALSE}, - {OPTION_CLONE_REFRESH,"CloneRefresh",OPTV_INTEGER, {0}, FALSE}, {OPTION_CHECKDEVICES, "CheckDevices",OPTV_BOOLEAN, {0}, FALSE}, {OPTION_FIXEDPIPE, "FixedPipe", OPTV_ANYSTR, {0}, FALSE}, {OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE}, @@ -1387,23 +1383,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) i830_crtc_init(pScrn, i); } - if (xf86ReturnOptValBool(pI830->Options, OPTION_CLONE, FALSE)) { - if (num_pipe == 1) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Can't enable Clone Mode because this is a single pipe device\n"); - PreInitCleanup(pScrn); - return FALSE; - } - if (pI830->entityPrivate) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Can't enable Clone Mode because second head is configured\n"); - PreInitCleanup(pScrn); - return FALSE; - } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling Clone Mode\n"); - pI830->Clone = TRUE; - } - SaveHWState(pScrn); /* Do an initial detection of the outputs while none are configured on yet. * This will give us some likely legitimate response for later if both @@ -3240,12 +3219,6 @@ I830LeaveVT(int scrnIndex, int flags) I830VideoSwitchModeBefore(pScrn, NULL); #endif - if (pI830->Clone) { - /* Ensure we don't try and setup modes on a clone head */ - pI830->CloneHDisplay = 0; - pI830->CloneVDisplay = 0; - } - if (!I830IsPrimary(pScrn)) { I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); if (!pI8301->GttBound) { diff --git a/src/i830_video.c b/src/i830_video.c index a3bfda8d..3aad1aa5 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -954,7 +954,7 @@ I830SetPortAttribute(ScrnInfoPtr pScrn, overlay->OCLRC1 = pPriv->saturation; overlay->OCMD &= ~OVERLAY_ENABLE; OVERLAY_UPDATE; - } else if (pI830->Clone && attribute == xvPipe) { + } else if (attribute == xvPipe) { if ((value < 0) || (value > 1)) return BadValue; pPriv->pipe = value; @@ -3554,18 +3554,6 @@ I830VideoSwitchModeAfter(ScrnInfoPtr pScrn, DisplayModePtr mode) pPriv->overlayOK = TRUE; -#if 0 - /* XXX Must choose pipe wisely */ - /* ensure pipe is updated on mode switch */ - if (!pI830->Clone) { - if (pPriv->pipe != pI830->pipe) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Changing XVideo pipe (%d to %d).\n", pPriv->pipe, pI830->pipe); - pPriv->pipe = pI830->pipe; - } - } -#endif - if (!IS_I965G(pI830)) { if (pPriv->pipe == 0) { if (INREG(PIPEACONF) & PIPEACONF_DOUBLE_WIDE) { From 3f3791ba2ece8e8a7aa3a5676f5f6361862a292c Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 11 Dec 2006 15:20:15 -0800 Subject: [PATCH 04/32] Remove remnants of old savedCurrentMode hack. Man, that was gross. --- src/i830.h | 4 ---- src/i830_display.c | 13 ------------- 2 files changed, 17 deletions(-) diff --git a/src/i830.h b/src/i830.h index 2a7a1d88..9809f352 100644 --- a/src/i830.h +++ b/src/i830.h @@ -242,10 +242,6 @@ typedef struct _I830Rec { int cpp; DisplayModePtr currentMode; - /* Mode saved during randr reprobe, which will need to be freed at the point - * of the next SwitchMode, when we lose this last reference to it. - */ - DisplayModePtr savedCurrentMode; I830EntPtr entityPrivate; int init; diff --git a/src/i830_display.c b/src/i830_display.c index 6206243e..b2d9e351 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -976,19 +976,6 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) (int)(pMode->HDisplay * pMode->VDisplay * pMode->VRefresh / 1000000)); - if (pI830->savedCurrentMode) { - /* We're done with the currentMode that the last randr probe had left - * behind, so free it. - */ - xfree(pI830->savedCurrentMode->name); - xfree(pI830->savedCurrentMode); - pI830->savedCurrentMode = NULL; - - /* If HW cursor currently showing, reset cursor state */ - if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) - pI830->CursorInfoRec->ShowCursor(pScrn); - } - i830DisableUnusedFunctions(pScrn); i830DescribeOutputConfiguration(pScrn); From c8c1fb64ccecfb88f9923ad65c9898aa44692260 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 11 Dec 2006 16:02:29 -0800 Subject: [PATCH 05/32] Move the overlay mode switch status updates to when we enable/disable crtcs. This should help if we mode switch with randr during video playback, and also simplifies the code by moving the protection all to one place. --- src/i830.h | 3 +- src/i830_display.c | 6 ++ src/i830_driver.c | 43 ++------------- src/i830_video.c | 134 ++++++++++++++++++++------------------------- 4 files changed, 70 insertions(+), 116 deletions(-) diff --git a/src/i830.h b/src/i830.h index 9809f352..64a32dc3 100644 --- a/src/i830.h +++ b/src/i830.h @@ -517,8 +517,7 @@ extern Bool I830DGAInit(ScreenPtr pScreen); #ifdef I830_XV extern void I830InitVideo(ScreenPtr pScreen); -extern void I830VideoSwitchModeBefore(ScrnInfoPtr pScrn, DisplayModePtr mode); -extern void I830VideoSwitchModeAfter(ScrnInfoPtr pScrn, DisplayModePtr mode); +extern void i830_crtc_dpms_video(xf86CrtcPtr crtc, Bool on); #endif extern Bool I830AllocateRotatedBuffer(ScrnInfoPtr pScrn, const int flags); diff --git a/src/i830_display.c b/src/i830_display.c index b2d9e351..f05b5c73 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -511,8 +511,14 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mode) /* Enable the plane */ temp = INREG(dspcntr_reg); OUTREG(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE); + + /* Give the overlay scaler a chance to enable if it's on this pipe */ + i830_crtc_dpms_video(crtc, TRUE); break; case DPMSModeOff: + /* 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); diff --git a/src/i830_driver.c b/src/i830_driver.c index 19f94260..46973e77 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -2244,7 +2244,6 @@ RestoreHWState(ScrnInfoPtr pScrn) I830Ptr pI830 = I830PTR(pScrn); vgaHWPtr hwp = VGAHWPTR(pScrn); vgaRegPtr vgaReg = &hwp->SavedReg; - CARD32 temp; int i; DPRINTF(PFX, "RestoreHWState\n"); @@ -2259,19 +2258,11 @@ RestoreHWState(ScrnInfoPtr pScrn) output->funcs->dpms(output, DPMSModeOff); } - /* Disable display planes */ - temp = INREG(DSPACNTR); - OUTREG(DSPACNTR, temp & ~DISPLAY_PLANE_ENABLE); - temp = INREG(DSPBCNTR); - OUTREG(DSPBCNTR, temp & ~DISPLAY_PLANE_ENABLE); - - /* Next, disable display pipes */ - temp = INREG(PIPEACONF); - OUTREG(PIPEACONF, temp & ~PIPEACONF_ENABLE); - temp = INREG(PIPEBCONF); - OUTREG(PIPEBCONF, temp & ~PIPEBCONF_ENABLE); - - i830WaitForVblank(pScrn); + /* Disable pipes */ + for (i = 0; i < pI830->xf86_config.num_crtc; i++) { + xf86CrtcPtr crtc = pI830->xf86_config.crtc[i]; + crtc->funcs->dpms(crtc, DPMSModeOff); + } OUTREG(FPA0, pI830->saveFPA0); OUTREG(FPA1, pI830->saveFPA1); @@ -3214,11 +3205,6 @@ I830LeaveVT(int scrnIndex, int flags) i830SetHotkeyControl(pScrn, HOTKEY_BIOS_SWITCH); -#ifdef I830_XV - /* Give the video overlay code a chance to shutdown. */ - I830VideoSwitchModeBefore(pScrn, NULL); -#endif - if (!I830IsPrimary(pScrn)) { I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); if (!pI8301->GttBound) { @@ -3319,10 +3305,6 @@ I830EnterVT(int scrnIndex, int flags) #ifdef XF86DRI I830DRISetVBlankInterrupt (pScrn, TRUE); #endif - -#ifdef I830_XV - I830VideoSwitchModeAfter(pScrn, pScrn->currentMode); -#endif ResetState(pScrn, TRUE); SetHWOperatingState(pScrn); @@ -3396,11 +3378,6 @@ I830SwitchMode(int scrnIndex, DisplayModePtr mode, int flags) DPRINTF(PFX, "I830SwitchMode: mode == %p\n", mode); -#ifdef I830_XV - /* Give the video overlay code a chance to see the new mode. */ - I830VideoSwitchModeBefore(pScrn, mode); -#endif - /* Sync the engine before mode switch */ i830WaitSync(pScrn); @@ -3434,18 +3411,8 @@ I830SwitchMode(int scrnIndex, DisplayModePtr mode, int flags) xf86DrvMsg(scrnIndex, X_INFO, "Failed to restore previous mode (SwitchMode)\n"); } - -#ifdef I830_XV - /* Give the video overlay code a chance to see the new mode. */ - I830VideoSwitchModeAfter(pScrn, pI830->currentMode); -#endif } else { pI830->currentMode = mode; - -#ifdef I830_XV - /* Give the video overlay code a chance to see the new mode. */ - I830VideoSwitchModeAfter(pScrn, mode); -#endif } return ret; diff --git a/src/i830_video.c b/src/i830_video.c index 3aad1aa5..986d36a1 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -738,10 +738,10 @@ I830SetupImageVideoOverlay(ScreenPtr pScreen) /* * Initialise pPriv->overlayOK. Set it to TRUE here so that a warning will - * be generated if I830VideoSwitchModeAfter() sets it to FALSE. + * be generated if i830_crtc_dpms_video() sets it to FALSE during mode + * setup. */ pPriv->overlayOK = TRUE; - I830VideoSwitchModeAfter(pScrn, pScrn->currentMode); pI830->BlockHandler = pScreen->BlockHandler; pScreen->BlockHandler = I830BlockHandler; @@ -3511,95 +3511,77 @@ I830InitOffscreenImages(ScreenPtr pScreen) } void -I830VideoSwitchModeBefore(ScrnInfoPtr pScrn, DisplayModePtr mode) +i830_crtc_dpms_video(xf86CrtcPtr crtc, Bool on) { + ScrnInfoPtr pScrn = crtc->scrn; I830Ptr pI830 = I830PTR(pScrn); I830PortPrivPtr pPriv; + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; - if (!pI830->adaptor) { + if (pI830->adaptor == NULL) + return; + + /* No overlay scaler on the 965. */ + if (IS_I965G(pI830)) return; - } pPriv = GET_PORT_PRIVATE(pScrn); - if (!pPriv) { - xf86ErrorF("pPriv isn't set\n"); - return; - } - - /* We stop the video when mode switching, just so we don't lockup - * the engine. The overlayOK will determine whether we can re-enable - * with the current video on completion of the mode switch. - */ - I830StopVideo(pScrn, pPriv, TRUE); - - pPriv->overlayOK = FALSE; - - pPriv->oneLineMode = FALSE; -} - -void -I830VideoSwitchModeAfter(ScrnInfoPtr pScrn, DisplayModePtr mode) -{ - I830Ptr pI830 = I830PTR(pScrn); - I830PortPrivPtr pPriv; - int size, hsize, vsize, active; - - if (!pI830->adaptor) { - return; - } - pPriv = GET_PORT_PRIVATE(pScrn); - if (!pPriv) + /* Check if it's the pipe the overlay is on */ + if (intel_crtc->pipe != pPriv->pipe) return; - pPriv->overlayOK = TRUE; + if (on) { + int size, hsize, vsize, active; + int pipeconf_reg = pPriv->pipe == 0 ? PIPEACONF : PIPEBCONF; + char pipename = pPriv->pipe == 0 ? 'A' : 'B'; - if (!IS_I965G(pI830)) { - if (pPriv->pipe == 0) { - if (INREG(PIPEACONF) & PIPEACONF_DOUBLE_WIDE) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Disabling XVideo output because Pipe A is in double-wide mode.\n"); - pPriv->overlayOK = FALSE; - } else if (!pPriv->overlayOK) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Re-enabling XVideo output because Pipe A is now in single-wide mode.\n"); - pPriv->overlayOK = TRUE; - } + pPriv->overlayOK = TRUE; + + if (INREG(pipeconf_reg) & PIPEACONF_DOUBLE_WIDE) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Disabling XVideo output because Pipe %c is in " + "double-wide mode.\n", pipename); + pPriv->overlayOK = FALSE; + } else if (!pPriv->overlayOK) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Re-enabling XVideo output because Pipe %c is now in " + "single-wide mode.\n", pipename); + pPriv->overlayOK = TRUE; } - if (pPriv->pipe == 1) { - if (INREG(PIPEBCONF) & PIPEBCONF_DOUBLE_WIDE) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Disabling XVideo output because Pipe B is in double-wide mode.\n"); - pPriv->overlayOK = FALSE; - } else if (!pPriv->overlayOK) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Re-enabling XVideo output because Pipe B is now in single-wide mode.\n"); - pPriv->overlayOK = TRUE; - } - } - } + /* Check we have an LFP connected */ + if (i830PipeHasType(pI830->xf86_config.crtc[pPriv->pipe], + I830_OUTPUT_LVDS)) { + size = pPriv->pipe ? INREG(PIPEBSRC) : INREG(PIPEASRC); + hsize = (size >> 16) & 0x7FF; + vsize = size & 0x7FF; + int vtotal_reg = pPriv->pipe ? VTOTAL_A : VTOTAL_B; + active = INREG(vtotal_reg) & 0x7FF; - /* Check we have an LFP connected */ - if (i830PipeHasType (pI830->xf86_config.crtc[pPriv->pipe], I830_OUTPUT_LVDS)) - { - size = pPriv->pipe ? INREG(PIPEBSRC) : INREG(PIPEASRC); - hsize = (size >> 16) & 0x7FF; - vsize = size & 0x7FF; - active = pPriv->pipe ? (INREG(VTOTAL_B) & 0x7FF) : (INREG(VTOTAL_A) & 0x7FF); + if (vsize < active && hsize > 1024) + I830SetOneLineModeRatio(pScrn); - if (vsize < active && hsize > 1024) - I830SetOneLineModeRatio(pScrn); - - if (pPriv->scaleRatio & 0xFFFE0000) { - /* Possible bogus ratio, using in-accurate fallback */ - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Bogus panel fit register, Xvideo positioning may not be accurate.\n"); - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Using fallback ratio - was 0x%x, now 0x%x\n", pPriv->scaleRatio, (int)(((float)active * 65536)/(float)vsize)); - - - pPriv->scaleRatio = (int)(((float)active * 65536) / (float)vsize); + if (pPriv->scaleRatio & 0xFFFE0000) { + /* Possible bogus ratio, using in-accurate fallback */ + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Bogus panel fit register, Xvideo positioning may not " + "be accurate.\n"); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Using fallback ratio - was 0x%x, now 0x%x\n", + pPriv->scaleRatio, + (int)(((float)active * 65536)/(float)vsize)); + + pPriv->scaleRatio = (int)(((float)active * 65536) / (float)vsize); + } } + } else { + /* We stop the video when mode switching, so we don't lock up + * the engine. The overlayOK will determine whether we can re-enable + * with the current video on completion of the mode switch. + */ + I830StopVideo(pScrn, pPriv, TRUE); + pPriv->overlayOK = FALSE; + pPriv->oneLineMode = FALSE; } } From ce54538b905eb329f45c1b9b15e95ddce4a7927f Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 8 Dec 2006 08:26:30 -0800 Subject: [PATCH 06/32] Add a hack for DDC on my Mac Mini. --- src/i830_sdvo.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index 87dc9d9e..077e6c17 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -983,6 +983,31 @@ i830_sdvo_detect(xf86OutputPtr output) return XF86OutputStatusDisconnected; } +static DisplayModePtr +i830_sdvo_get_modes(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); + DisplayModePtr modes; + xf86OutputPtr crt; + + modes = i830_ddc_get_modes(output); + if (modes != NULL) + return NULL; + + /* Mac mini hack. On this device, I get DDC through the analog, which + * load-detects as disconnected. I fail to DDC through the SDVO DDC, + * but it does load-detect as connected. So, just steal the DDC bits from + * analog when we fail at finding it the right way. + */ + crt = pI830->xf86_config.output[0]; + if (crt->funcs->detect(crt) == XF86OutputStatusDisconnected) { + return crt->funcs->get_modes(crt); + } + + return NULL; +} + static void i830_sdvo_destroy (xf86OutputPtr output) { @@ -1007,7 +1032,7 @@ static const xf86OutputFuncsRec i830_sdvo_output_funcs = { .mode_fixup = i830_sdvo_mode_fixup, .mode_set = i830_sdvo_mode_set, .detect = i830_sdvo_detect, - .get_modes = i830_ddc_get_modes, + .get_modes = i830_sdvo_get_modes, .destroy = i830_sdvo_destroy }; From 91a538beadc17155be395ea2c8109a0958a969bd Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Sat, 9 Dec 2006 15:58:47 -0800 Subject: [PATCH 07/32] More debugging output for SDVO. --- src/i810_reg.h | 10 ++++++++++ src/i830_debug.c | 47 ++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/src/i810_reg.h b/src/i810_reg.h index d5250245..ce8407da 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -888,6 +888,16 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /** @} */ #define DPLL_TEST 0x606c +# define DPLLB_TEST_SDVO_DIV_1 (0 << 22) +# define DPLLB_TEST_SDVO_DIV_2 (1 << 22) +# define DPLLB_TEST_SDVO_DIV_4 (2 << 22) +# define DPLLB_TEST_SDVO_DIV_MASK (3 << 22) +# define DPLLB_TEST_N_BYPASS (1 << 19) +# define DPLLB_TEST_M_BYPASS (1 << 18) +# define DPLLB_INPUT_BUFFER_ENABLE (1 << 16) +# define DPLLA_TEST_N_BYPASS (1 << 3) +# define DPLLA_TEST_M_BYPASS (1 << 2) +# define DPLLA_INPUT_BUFFER_ENABLE (1 << 0) #define D_STATE 0x6104 #define DSPCLK_GATE_D 0x6200 diff --git a/src/i830_debug.c b/src/i830_debug.c index 8c8b95ee..c2096a50 100644 --- a/src/i830_debug.c +++ b/src/i830_debug.c @@ -160,8 +160,8 @@ DEBUGSTRING(i830_debug_dpll) } if (IS_I945G(pI830) || IS_I945GM(pI830)) { sprintf(sdvoextra, ", SDVO mult %d", - (int)(val & SDVO_MULTIPLIER_MASK) >> - SDVO_MULTIPLIER_SHIFT_HIRES); + (int)((val & SDVO_MULTIPLIER_MASK) >> + SDVO_MULTIPLIER_SHIFT_HIRES) + 1); } else { sdvoextra[0] = '\0'; } @@ -172,6 +172,22 @@ DEBUGSTRING(i830_debug_dpll) fpextra, sdvoextra); } +DEBUGSTRING(i830_debug_dpll_test) +{ + char *dpllandiv = val & DPLLA_TEST_N_BYPASS ? ", DPLLA N bypassed" : ""; + char *dpllamdiv = val & DPLLA_TEST_M_BYPASS ? ", DPLLA M bypassed" : ""; + char *dpllainput = val & DPLLA_INPUT_BUFFER_ENABLE ? + "" : ", DPLLA input buffer disabled"; + char *dpllbndiv = val & DPLLB_TEST_N_BYPASS ? ", DPLLB N bypassed" : ""; + char *dpllbmdiv = val & DPLLB_TEST_M_BYPASS ? ", DPLLB M bypassed" : ""; + char *dpllbinput = val & DPLLB_INPUT_BUFFER_ENABLE ? + "" : ", DPLLB input buffer disabled"; + + return XNFprintf("%s%s%s%s%s%s", + dpllandiv, dpllamdiv, dpllainput, + dpllbndiv, dpllbmdiv, dpllbinput); +} + DEBUGSTRING(i830_debug_lvds) { char pipe = val & LVDS_PIPEB_SELECT ? 'B' : 'A'; @@ -180,6 +196,27 @@ DEBUGSTRING(i830_debug_lvds) return XNFprintf("%s, pipe %c", enable, pipe); } +DEBUGSTRING(i830_debug_sdvo) +{ + char *enable = val & SDVO_ENABLE ? "enabled" : "disabled"; + char pipe = val & SDVO_PIPE_B_SELECT ? 'B' : 'A'; + char *stall = val & SDVO_STALL_SELECT ? "enabled" : "disabled"; + char *detected = val & SDVO_DETECTED ? "" : "not "; + char *gang = val & SDVOC_GANG_MODE ? ", gang mode" : ""; + char sdvoextra[20]; + + if (IS_I915G(pI830) || IS_I915GM(pI830)) { + sprintf(sdvoextra, ", SDVO mult %d", + (int)((val & SDVO_PORT_MULTIPLY_MASK) >> + SDVO_PORT_MULTIPLY_SHIFT) + 1); + } else { + sdvoextra[0] = '\0'; + } + + return XNFprintf("%s, pipe %c, stall %s, %sdetected%s%s", + enable, pipe, stall, detected, sdvoextra, gang); +} + #define DEFINEREG(reg) \ { reg, #reg, NULL, 0 } #define DEFINEREG2(reg, func) \ @@ -194,14 +231,14 @@ static struct i830SnapshotRec { DEFINEREG(VCLK_DIVISOR_VGA0), DEFINEREG(VCLK_DIVISOR_VGA1), DEFINEREG(VCLK_POST_DIV), - DEFINEREG(DPLL_TEST), + DEFINEREG2(DPLL_TEST, i830_debug_dpll_test), DEFINEREG(D_STATE), DEFINEREG(DSPCLK_GATE_D), DEFINEREG(RENCLK_GATE_D1), DEFINEREG(RENCLK_GATE_D2), /* DEFINEREG(RAMCLK_GATE_D), CRL only */ - DEFINEREG(SDVOB), - DEFINEREG(SDVOC), + DEFINEREG2(SDVOB, i830_debug_sdvo), + DEFINEREG2(SDVOC, i830_debug_sdvo), /* DEFINEREG(UDIB_SVB_SHB_CODES), CRL only */ /* DEFINEREG(UDIB_SHA_BLANK_CODES), CRL only */ DEFINEREG(SDVOUDI), From 668ae6ce3c3c4b93a58749fd44ef32451adb6f9c Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 12 Dec 2006 11:39:40 -0800 Subject: [PATCH 08/32] Set the SDVO port to on before sending the SDVO output on command. --- src/i830_sdvo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index 077e6c17..8619d026 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -701,8 +701,8 @@ i830_sdvo_dpms(xf86OutputPtr output, int mode) i830_sdvo_set_active_outputs(output, 0); OUTREG(dev_priv->output_device, INREG(dev_priv->output_device) & ~SDVO_ENABLE); } else { - i830_sdvo_set_active_outputs(output, dev_priv->active_outputs); OUTREG(dev_priv->output_device, INREG(dev_priv->output_device) | SDVO_ENABLE); + i830_sdvo_set_active_outputs(output, dev_priv->active_outputs); } } From 838af10b85ee8c085c6d2c4fbe18fd90b2be9d3f Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 12 Dec 2006 13:45:41 -0800 Subject: [PATCH 09/32] Move PrintErrorState and CheckInheritedErrors code to i830_debug.c. --- src/common.h | 2 +- src/i830.h | 2 - src/i830_accel.c | 3 +- src/i830_debug.c | 161 ++++++++++++++++++++++++++++++++++++++++++++++ src/i830_debug.h | 4 ++ src/i830_driver.c | 154 +------------------------------------------- src/i830_video.c | 2 +- 7 files changed, 170 insertions(+), 158 deletions(-) diff --git a/src/common.h b/src/common.h index dd3fed62..540983b5 100644 --- a/src/common.h +++ b/src/common.h @@ -96,7 +96,7 @@ extern void I830DPRINTF_stub(const char *filename, int line, const char *function, const char *fmt, ...); #ifdef _I830_H_ -#define PrintErrorState I830PrintErrorState +#define PrintErrorState i830_dump_error_state #define WaitRingFunc I830WaitLpRing #define RecPtr pI830 #else diff --git a/src/i830.h b/src/i830.h index 64a32dc3..292374c1 100644 --- a/src/i830.h +++ b/src/i830.h @@ -499,8 +499,6 @@ typedef struct _I830Rec { extern int I830WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis); extern void I830SetPIOAccess(I830Ptr pI830); extern void I830SetMMIOAccess(I830Ptr pI830); -extern void I830PrintErrorState(ScrnInfoPtr pScrn); -extern void I965PrintErrorState(ScrnInfoPtr pScrn); extern void I830Sync(ScrnInfoPtr pScrn); extern void I830InitHWCursor(ScrnInfoPtr pScrn); extern void I830SetPipeCursor (xf86CrtcPtr crtc, Bool force); diff --git a/src/i830_accel.c b/src/i830_accel.c index 6ad62d1f..2260b71b 100644 --- a/src/i830_accel.c +++ b/src/i830_accel.c @@ -58,6 +58,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "xaarop.h" #include "i830.h" #include "i810_reg.h" +#include "i830_debug.h" int I830WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis) @@ -99,7 +100,7 @@ I830WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis) } else if (now - start > timeout_millis) { ErrorF("Error in I830WaitLpRing(), now is %d, start is %d\n", now, start); - I830PrintErrorState(pScrn); + i830_dump_error_state(pScrn); ErrorF("space: %d wanted %d\n", ring->space, n); #ifdef XF86DRI if (pI830->directRenderingEnabled) { diff --git a/src/i830_debug.c b/src/i830_debug.c index c2096a50..7446a22b 100644 --- a/src/i830_debug.c +++ b/src/i830_debug.c @@ -522,3 +522,164 @@ void i830DumpRegs (ScrnInfoPtr pScrn) } xf86DrvMsg (pScrn->scrnIndex, X_INFO, "DumpRegsEnd\n"); } + +/* Famous last words + */ +void +i830_dump_error_state(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + + ErrorF("pgetbl_ctl: 0x%lx pgetbl_err: 0x%lx\n", + (unsigned long)INREG(PGETBL_CTL), (unsigned long)INREG(PGE_ERR)); + + ErrorF("ipeir: %lx iphdr: %lx\n", (unsigned long)INREG(IPEIR), + (unsigned long)INREG(IPEHR)); + + ErrorF("LP ring tail: %lx head: %lx len: %lx start %lx\n", + (unsigned long)INREG(LP_RING + RING_TAIL), + (unsigned long)INREG(LP_RING + RING_HEAD) & HEAD_ADDR, + (unsigned long)INREG(LP_RING + RING_LEN), + (unsigned long)INREG(LP_RING + RING_START)); + + ErrorF("eir: %x esr: %x emr: %x\n", + INREG16(EIR), INREG16(ESR), INREG16(EMR)); + + ErrorF("instdone: %x instpm: %x\n", INREG16(INST_DONE), INREG8(INST_PM)); + + ErrorF("memmode: %lx instps: %lx\n", (unsigned long)INREG(MEMMODE), + (unsigned long)INREG(INST_PS)); + + ErrorF("hwstam: %x ier: %x imr: %x iir: %x\n", + INREG16(HWSTAM), INREG16(IER), INREG16(IMR), INREG16(IIR)); +} + +void +i965_dump_error_state(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + + ErrorF("pgetbl_ctl: 0x%lx pgetbl_err: 0x%lx\n", + INREG(PGETBL_CTL), INREG(PGE_ERR)); + + ErrorF("ipeir: %lx iphdr: %lx\n", INREG(IPEIR_I965), INREG(IPEHR_I965)); + + ErrorF("LP ring tail: %lx head: %lx len: %lx start %lx\n", + INREG(LP_RING + RING_TAIL), + INREG(LP_RING + RING_HEAD) & HEAD_ADDR, + INREG(LP_RING + RING_LEN), INREG(LP_RING + RING_START)); + + ErrorF("Err ID (eir): %x Err Status (esr): %x Err Mask (emr): %x\n", + (int)INREG(EIR), (int)INREG(ESR), (int)INREG(EMR)); + + ErrorF("instdone: %x instdone_1: %x\n", (int)INREG(INST_DONE_I965), + (int)INREG(INST_DONE_1)); + ErrorF("instpm: %x\n", (int)INREG(INST_PM)); + + ErrorF("memmode: %lx instps: %lx\n", INREG(MEMMODE), INREG(INST_PS_I965)); + + ErrorF("HW Status mask (hwstam): %x\nIRQ enable (ier): %x " + "imr: %x iir: %x\n", + (int)INREG(HWSTAM), (int)INREG(IER), (int)INREG(IMR), + (int)INREG(IIR)); + + ErrorF("acthd: %lx dma_fadd_p: %lx\n", INREG(ACTHD), INREG(DMA_FADD_P)); + ErrorF("ecoskpd: %lx excc: %lx\n", INREG(ECOSKPD), INREG(EXCC)); + + ErrorF("cache_mode: %x/%x\n", (int)INREG(CACHE_MODE_0), + (int)INREG(CACHE_MODE_1)); + ErrorF("mi_arb_state: %x\n", (int)INREG(MI_ARB_STATE)); + + ErrorF("IA_VERTICES_COUNT_QW %x/%x\n", + (int)INREG(IA_VERTICES_COUNT_QW), + (int)INREG(IA_VERTICES_COUNT_QW+4)); + ErrorF("IA_PRIMITIVES_COUNT_QW %x/%x\n", + (int)INREG(IA_PRIMITIVES_COUNT_QW), + (int)INREG(IA_PRIMITIVES_COUNT_QW+4)); + + ErrorF("VS_INVOCATION_COUNT_QW %x/%x\n", + (int)INREG(VS_INVOCATION_COUNT_QW), + (int)INREG(VS_INVOCATION_COUNT_QW+4)); + + ErrorF("GS_INVOCATION_COUNT_QW %x/%x\n", + (int)INREG(GS_INVOCATION_COUNT_QW), + (int)INREG(GS_INVOCATION_COUNT_QW+4)); + ErrorF("GS_PRIMITIVES_COUNT_QW %x/%x\n", + (int)INREG(GS_PRIMITIVES_COUNT_QW), + (int)INREG(GS_PRIMITIVES_COUNT_QW+4)); + + ErrorF("CL_INVOCATION_COUNT_QW %x/%x\n", + (int)INREG(CL_INVOCATION_COUNT_QW), + (int)INREG(CL_INVOCATION_COUNT_QW+4)); + ErrorF("CL_PRIMITIVES_COUNT_QW %x/%x\n", + (int)INREG(CL_PRIMITIVES_COUNT_QW), + (int)INREG(CL_PRIMITIVES_COUNT_QW+4)); + + ErrorF("PS_INVOCATION_COUNT_QW %x/%x\n", + (int)INREG(PS_INVOCATION_COUNT_QW), + (int)INREG(PS_INVOCATION_COUNT_QW+4)); + ErrorF("PS_DEPTH_COUNT_QW %x/%x\n", + (int)INREG(PS_DEPTH_COUNT_QW), + (int)INREG(PS_DEPTH_COUNT_QW+4)); + + ErrorF("WIZ_CTL %x\n", (int)INREG(WIZ_CTL)); + ErrorF("TS_CTL %x TS_DEBUG_DATA %x\n", (int)INREG(TS_CTL), + (int)INREG(TS_DEBUG_DATA)); + ErrorF("TD_CTL %x / %x\n", (int)INREG(TD_CTL), (int)INREG(TD_CTL2)); +} + +/** + * Checks the hardware error state bits. + * + * \return TRUE if any errors were found. + */ +Bool +i830_check_error_state(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + int errors = 0, fatal = 0; + unsigned long temp, head, tail; + + if (!I830IsPrimary(pScrn)) return TRUE; + + /* Check first for page table errors */ + temp = INREG(PGE_ERR); + if (temp != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "PGTBL_ER is 0x%08lx\n", temp); + errors++; + } + temp = INREG(PGETBL_CTL); + if (!(temp & 1)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "PGTBL_CTL (0x%08lx) indicates GTT is disabled\n", temp); + errors++; + } + temp = INREG(LP_RING + RING_LEN); + if (temp & 1) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "PRB0_CTL (0x%08lx) indicates ring buffer enabled\n", temp); + errors++; + } + head = INREG(LP_RING + RING_HEAD); + tail = INREG(LP_RING + RING_TAIL); + if ((tail & I830_TAIL_MASK) != (head & I830_HEAD_MASK)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "PRB0_HEAD (0x%08lx) and PRB0_TAIL (0x%08lx) indicate " + "ring buffer not flushed\n", head, tail); + errors++; + } + +#if 0 + if (errors) { + if (IS_I965G(pI830)) + i965_dump_error_state(pScrn); + else + i830_dump_error_state(pScrn); + } +#endif + + if (fatal) + FatalError("i830_check_error_state: can't recover from the above\n"); + + return (errors != 0); +} diff --git a/src/i830_debug.h b/src/i830_debug.h index a365085c..2d2e72bf 100644 --- a/src/i830_debug.h +++ b/src/i830_debug.h @@ -28,3 +28,7 @@ void i830TakeRegSnapshot(ScrnInfoPtr pScrn); void i830CompareRegsToSnapshot(ScrnInfoPtr pScrn, char *where); void i830DumpRegs (ScrnInfoPtr pScrn); +void i830_dump_error_state(ScrnInfoPtr pScrn); +void i965_dump_error_state(ScrnInfoPtr pScrn); +Bool i830_check_error_state(ScrnInfoPtr pScrn); + diff --git a/src/i830_driver.c b/src/i830_driver.c index 46973e77..78804de3 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1947,61 +1947,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) return TRUE; } -/* - * As the name says. Check that the initial state is reasonable. - * If any unrecoverable problems are found, bail out here. - */ -static Bool -CheckInheritedState(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - int errors = 0, fatal = 0; - unsigned long temp, head, tail; - - if (!I830IsPrimary(pScrn)) return TRUE; - - /* Check first for page table errors */ - temp = INREG(PGE_ERR); - if (temp != 0) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "PGTBL_ER is 0x%08lx\n", temp); - errors++; - } - temp = INREG(PGETBL_CTL); - if (!(temp & 1)) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "PGTBL_CTL (0x%08lx) indicates GTT is disabled\n", temp); - errors++; - } - temp = INREG(LP_RING + RING_LEN); - if (temp & 1) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "PRB0_CTL (0x%08lx) indicates ring buffer enabled\n", temp); - errors++; - } - head = INREG(LP_RING + RING_HEAD); - tail = INREG(LP_RING + RING_TAIL); - if ((tail & I830_TAIL_MASK) != (head & I830_HEAD_MASK)) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "PRB0_HEAD (0x%08lx) and PRB0_TAIL (0x%08lx) indicate " - "ring buffer not flushed\n", head, tail); - errors++; - } - -#if 0 - if (errors) { - if (IS_I965G(pI830)) - I965PrintErrorState(pScrn); - else - I830PrintErrorState(pScrn); - } -#endif - - if (fatal) - FatalError("CheckInheritedState: can't recover from the above\n"); - - return (errors != 0); -} - /* * Reset registers that it doesn't make sense to save/restore to a sane state. * This is basically the ring buffer and fence registers. Restoring these @@ -2366,103 +2311,6 @@ InitRegisterRec(ScrnInfoPtr pScrn) i830Reg->Fence[i] = 0; } -/* Famous last words - */ -void -I830PrintErrorState(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - - ErrorF("pgetbl_ctl: 0x%lx pgetbl_err: 0x%lx\n", - (unsigned long)INREG(PGETBL_CTL), (unsigned long)INREG(PGE_ERR)); - - ErrorF("ipeir: %lx iphdr: %lx\n", (unsigned long)INREG(IPEIR), - (unsigned long)INREG(IPEHR)); - - ErrorF("LP ring tail: %lx head: %lx len: %lx start %lx\n", - (unsigned long)INREG(LP_RING + RING_TAIL), - (unsigned long)INREG(LP_RING + RING_HEAD) & HEAD_ADDR, - (unsigned long)INREG(LP_RING + RING_LEN), - (unsigned long)INREG(LP_RING + RING_START)); - - ErrorF("eir: %x esr: %x emr: %x\n", - INREG16(EIR), INREG16(ESR), INREG16(EMR)); - - ErrorF("instdone: %x instpm: %x\n", INREG16(INST_DONE), INREG8(INST_PM)); - - ErrorF("memmode: %lx instps: %lx\n", (unsigned long)INREG(MEMMODE), - (unsigned long)INREG(INST_PS)); - - ErrorF("hwstam: %x ier: %x imr: %x iir: %x\n", - INREG16(HWSTAM), INREG16(IER), INREG16(IMR), INREG16(IIR)); -} - -void -I965PrintErrorState(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - - ErrorF("pgetbl_ctl: 0x%lx pgetbl_err: 0x%lx\n", - INREG(PGETBL_CTL), INREG(PGE_ERR)); - - ErrorF("ipeir: %lx iphdr: %lx\n", INREG(IPEIR_I965), INREG(IPEHR_I965)); - - ErrorF("LP ring tail: %lx head: %lx len: %lx start %lx\n", - INREG(LP_RING + RING_TAIL), - INREG(LP_RING + RING_HEAD) & HEAD_ADDR, - INREG(LP_RING + RING_LEN), INREG(LP_RING + RING_START)); - - ErrorF("Err ID (eir): %x Err Status (esr): %x Err Mask (emr): %x\n", - (int)INREG(EIR), (int)INREG(ESR), (int)INREG(EMR)); - - ErrorF("instdone: %x instdone_1: %x\n", (int)INREG(INST_DONE_I965), - (int)INREG(INST_DONE_1)); - ErrorF("instpm: %x\n", (int)INREG(INST_PM)); - - ErrorF("memmode: %lx instps: %lx\n", INREG(MEMMODE), INREG(INST_PS_I965)); - - ErrorF("HW Status mask (hwstam): %x\nIRQ enable (ier): %x imr: %x iir: %x\n", - (int)INREG(HWSTAM), (int)INREG(IER), (int)INREG(IMR), - (int)INREG(IIR)); - - ErrorF("acthd: %lx dma_fadd_p: %lx\n", INREG(ACTHD), INREG(DMA_FADD_P)); - ErrorF("ecoskpd: %lx excc: %lx\n", INREG(ECOSKPD), INREG(EXCC)); - - ErrorF("cache_mode: %x/%x\n", (int)INREG(CACHE_MODE_0), - (int)INREG(CACHE_MODE_1)); - ErrorF("mi_arb_state: %x\n", (int)INREG(MI_ARB_STATE)); - - ErrorF("IA_VERTICES_COUNT_QW %x/%x\n", (int)INREG(IA_VERTICES_COUNT_QW), - (int)INREG(IA_VERTICES_COUNT_QW+4)); - ErrorF("IA_PRIMITIVES_COUNT_QW %x/%x\n", (int)INREG(IA_PRIMITIVES_COUNT_QW), - (int)INREG(IA_PRIMITIVES_COUNT_QW+4)); - - ErrorF("VS_INVOCATION_COUNT_QW %x/%x\n", (int)INREG(VS_INVOCATION_COUNT_QW), - (int)INREG(VS_INVOCATION_COUNT_QW+4)); - - ErrorF("GS_INVOCATION_COUNT_QW %x/%x\n", (int)INREG(GS_INVOCATION_COUNT_QW), - (int)INREG(GS_INVOCATION_COUNT_QW+4)); - ErrorF("GS_PRIMITIVES_COUNT_QW %x/%x\n", (int)INREG(GS_PRIMITIVES_COUNT_QW), - (int)INREG(GS_PRIMITIVES_COUNT_QW+4)); - - ErrorF("CL_INVOCATION_COUNT_QW %x/%x\n", (int)INREG(CL_INVOCATION_COUNT_QW), - (int)INREG(CL_INVOCATION_COUNT_QW+4)); - ErrorF("CL_PRIMITIVES_COUNT_QW %x/%x\n", (int)INREG(CL_PRIMITIVES_COUNT_QW), - (int)INREG(CL_PRIMITIVES_COUNT_QW+4)); - - ErrorF("PS_INVOCATION_COUNT_QW %x/%x\n", (int)INREG(PS_INVOCATION_COUNT_QW), - (int)INREG(PS_INVOCATION_COUNT_QW+4)); - ErrorF("PS_DEPTH_COUNT_QW %x/%x\n", (int)INREG(PS_DEPTH_COUNT_QW), - (int)INREG(PS_DEPTH_COUNT_QW+4)); - - ErrorF("WIZ_CTL %x\n", (int)INREG(WIZ_CTL)); - ErrorF("TS_CTL %x TS_DEBUG_DATA %x\n", (int)INREG(TS_CTL), - (int)INREG(TS_DEBUG_DATA)); - ErrorF("TD_CTL %x / %x\n", (int)INREG(TD_CTL), (int)INREG(TD_CTL2)); - - -} - static void I830PointerMoved(int index, int x, int y) { @@ -3277,7 +3125,7 @@ I830EnterVT(int scrnIndex, int flags) if (!I830BindAGPMemory(pScrn)) return FALSE; - CheckInheritedState(pScrn); + i830_check_error_state(pScrn); ResetState(pScrn, FALSE); SetHWOperatingState(pScrn); diff --git a/src/i830_video.c b/src/i830_video.c index 986d36a1..59794156 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -2794,7 +2794,7 @@ BroadwaterDisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, if (pI830->AccelInfoRec) (*pI830->AccelInfoRec->Sync)(pScrn); #if WATCH_STATS - I830PrintErrorState (pScrn); + i830_dump_error_state (pScrn); #endif } From ec45d7274333cccd20ad080facc8e995ad7b26b0 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 12 Dec 2006 13:54:49 -0800 Subject: [PATCH 10/32] Extend the error state reporting to cover ESR and decode PGTBL_ERR for 945. --- src/i810_reg.h | 38 +++++++++++++++++++++++++---- src/i830_debug.c | 61 +++++++++++++++++++++++++++++++++++++++++------ src/i830_driver.c | 5 +++- 3 files changed, 92 insertions(+), 12 deletions(-) diff --git a/src/i810_reg.h b/src/i810_reg.h index ce8407da..7c85cffd 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -398,8 +398,11 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define EIR 0x20B0 #define EMR 0x20B4 #define ESR 0x20B8 -#define IP_ERR 0x0001 -#define ERROR_RESERVED 0xffc6 +# define ERR_VERTEX_MAX (1 << 5) /* lpt/cst */ +# define ERR_PGTBL_ERROR (1 << 4) +# define ERR_DISPLAY_OVERLAY_UNDERRUN (1 << 3) +# define ERR_MAIN_MEMORY_REFRESH (1 << 2) +# define ERR_INSTRUCTION_ERROR (1 << 0) /* Interrupt Control Registers @@ -507,8 +510,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define PGETBL_SIZE_256KB (1 << 1) #define PGETBL_SIZE_128KB (2 << 1) -/* Register containing pge table error results, p276 +/** @defgroup PGE_ERR + * @{ */ +/** Page table debug register for i845 */ #define PGE_ERR 0x2024 #define PGE_ERR_ADDR_MASK 0xFFFFF000 #define PGE_ERR_ID_MASK 0x00000038 @@ -528,8 +533,33 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define PGE_ERR_ILLEGAL_TRX 0x00000004 #define PGE_ERR_LOCAL_MEM 0x00000005 #define PGE_ERR_TILED 0x00000006 +/** @} */ - +/** @defgroup PGTBL_ER + * @{ + */ +/** Page table debug register for i945 */ +# define PGTBL_ER 0x2024 +# define PGTBL_ERR_MT_TILING (1 << 27) +# define PGTBL_ERR_MT_GTT_PTE (1 << 26) +# define PGTBL_ERR_LC_TILING (1 << 25) +# define PGTBL_ERR_LC_GTT_PTE (1 << 24) +# define PGTBL_ERR_BIN_VERTEXDATA_GTT_PTE (1 << 23) +# define PGTBL_ERR_BIN_INSTRUCTION_GTT_PTE (1 << 22) +# define PGTBL_ERR_CS_VERTEXDATA_GTT_PTE (1 << 21) +# define PGTBL_ERR_CS_INSTRUCTION_GTT_PTE (1 << 20) +# define PGTBL_ERR_CS_GTT (1 << 19) +# define PGTBL_ERR_OVERLAY_TILING (1 << 18) +# define PGTBL_ERR_OVERLAY_GTT_PTE (1 << 16) +# define PGTBL_ERR_DISPC_TILING (1 << 14) +# define PGTBL_ERR_DISPC_GTT_PTE (1 << 12) +# define PGTBL_ERR_DISPB_TILING (1 << 10) +# define PGTBL_ERR_DISPB_GTT_PTE (1 << 8) +# define PGTBL_ERR_DISPA_TILING (1 << 6) +# define PGTBL_ERR_DISPA_GTT_PTE (1 << 4) +# define PGTBL_ERR_HOST_PTE_DATA (1 << 1) +# define PGTBL_ERR_HOST_GTT_PTE (1 << 0) +/** @} */ /* Page table entries loaded via mmio region, p323 */ diff --git a/src/i830_debug.c b/src/i830_debug.c index 7446a22b..25245fb2 100644 --- a/src/i830_debug.c +++ b/src/i830_debug.c @@ -637,17 +637,67 @@ Bool i830_check_error_state(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); - int errors = 0, fatal = 0; + int errors = 0; unsigned long temp, head, tail; if (!I830IsPrimary(pScrn)) return TRUE; - /* Check first for page table errors */ - temp = INREG(PGE_ERR); + temp = INREG16(ESR); if (temp != 0) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "PGTBL_ER is 0x%08lx\n", temp); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "ESR is 0x%08lx%s%s%s%s\n", temp, + temp & ERR_VERTEX_MAX ? ", max vertices exceeded" : "", + temp & ERR_PGTBL_ERROR ? ", page table error" : "", + temp & ERR_DISPLAY_OVERLAY_UNDERRUN ? + ", display/overlay underrun" : "", + temp & ERR_INSTRUCTION_ERROR ? ", instruction error" : ""); errors++; } + /* Check first for page table errors */ + if (!IS_I9XX(pI830)) { + temp = INREG(PGE_ERR); + if (temp != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "PGTBL_ER is 0x%08lx\n", temp); + errors++; + } + } else { + temp = INREG(PGTBL_ER); + if (temp != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "PGTBL_ER is 0x%08lx" + "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", temp, + temp & PGTBL_ERR_HOST_GTT_PTE ? ", host gtt pte" : "", + temp & PGTBL_ERR_HOST_PTE_DATA ? ", host pte data" : "", + temp & PGTBL_ERR_DISPA_GTT_PTE ? ", display A pte" : "", + temp & PGTBL_ERR_DISPA_TILING ? + ", display A tiling" : "", + temp & PGTBL_ERR_DISPB_GTT_PTE ? ", display B pte" : "", + temp & PGTBL_ERR_DISPB_TILING ? + ", display B tiling" : "", + temp & PGTBL_ERR_DISPC_GTT_PTE ? ", display C pte" : "", + temp & PGTBL_ERR_DISPC_TILING ? + ", display C tiling" : "", + temp & PGTBL_ERR_OVERLAY_GTT_PTE ? + ", overlay GTT PTE" : "", + temp & PGTBL_ERR_OVERLAY_TILING ? + ", overlay tiling" : "", + temp & PGTBL_ERR_CS_GTT ? ", CS GTT" : "", + temp & PGTBL_ERR_CS_INSTRUCTION_GTT_PTE ? + ", CS instruction GTT PTE" : "", + temp & PGTBL_ERR_CS_VERTEXDATA_GTT_PTE ? + ", CS vertex data GTT PTE" : "", + temp & PGTBL_ERR_BIN_INSTRUCTION_GTT_PTE ? + ", BIN instruction GTT PTE" : "", + temp & PGTBL_ERR_BIN_VERTEXDATA_GTT_PTE ? + ", BIN vertex data GTT PTE" : "", + temp & PGTBL_ERR_LC_GTT_PTE ? ", LC pte" : "", + temp & PGTBL_ERR_LC_TILING ? ", LC tiling" : "", + temp & PGTBL_ERR_MT_GTT_PTE ? ", MT pte" : "", + temp & PGTBL_ERR_MT_TILING ? ", MT tiling" : ""); + errors++; + } + } temp = INREG(PGETBL_CTL); if (!(temp & 1)) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, @@ -678,8 +728,5 @@ i830_check_error_state(ScrnInfoPtr pScrn) } #endif - if (fatal) - FatalError("i830_check_error_state: can't recover from the above\n"); - return (errors != 0); } diff --git a/src/i830_driver.c b/src/i830_driver.c index 78804de3..d8a9c9bc 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -3125,7 +3125,10 @@ I830EnterVT(int scrnIndex, int flags) if (!I830BindAGPMemory(pScrn)) return FALSE; - i830_check_error_state(pScrn); + if (i830_check_error_state(pScrn)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Existing errors found in hardware state\n"); + } ResetState(pScrn, FALSE); SetHWOperatingState(pScrn); From 54823ac39ce9666099d69196694643f04123cb4d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 12 Dec 2006 14:38:08 -0800 Subject: [PATCH 11/32] Move the SDVO sync detection to after we've turned the port on. --- src/i830_sdvo.c | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index 8619d026..7936abdf 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -556,12 +556,9 @@ i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode, struct i830_sdvo_priv *dev_priv = intel_output->dev_priv; xf86CrtcPtr crtc = output->crtc; I830CrtcPrivatePtr intel_crtc = crtc->driver_private; - Bool input1, input2; CARD32 sdvox; int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD; int sdvo_pixel_multiply; - int i; - CARD8 status; CARD16 width, height; CARD16 h_blank_len, h_sync_len, v_blank_len, v_sync_len; CARD16 h_sync_offset, v_sync_offset; @@ -675,18 +672,6 @@ i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode, } OUTREG(dev_priv->output_device, sdvox); - - for (i = 0; i < 2; i++) - i830WaitForVblank(pScrn); - - status = i830_sdvo_get_trained_inputs(output, &input1, &input2); - - /* Warn if the device reported failure to sync. */ - if (status == SDVO_CMD_STATUS_SUCCESS && !input1) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "First %s output reported failure to sync\n", - SDVO_NAME(dev_priv)); - } } static void @@ -699,10 +684,29 @@ i830_sdvo_dpms(xf86OutputPtr output, int mode) if (mode != DPMSModeOn) { i830_sdvo_set_active_outputs(output, 0); - OUTREG(dev_priv->output_device, INREG(dev_priv->output_device) & ~SDVO_ENABLE); + OUTREG(dev_priv->output_device, + INREG(dev_priv->output_device) & ~SDVO_ENABLE); } else { - OUTREG(dev_priv->output_device, INREG(dev_priv->output_device) | SDVO_ENABLE); + Bool input1, input2; + int i; + CARD8 status; + + OUTREG(dev_priv->output_device, + INREG(dev_priv->output_device) | SDVO_ENABLE); + i830_sdvo_set_active_outputs(output, dev_priv->active_outputs); + + for (i = 0; i < 2; i++) + i830WaitForVblank(pScrn); + + status = i830_sdvo_get_trained_inputs(output, &input1, &input2); + + /* Warn if the device reported failure to sync. */ + if (status == SDVO_CMD_STATUS_SUCCESS && !input1) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "First %s output reported failure to sync\n", + SDVO_NAME(dev_priv)); + } } } From 9776f6c68b3cdd5585e58e677c1b1318d9aedaf4 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 12 Dec 2006 16:02:47 -0800 Subject: [PATCH 12/32] Flush the plane changes in i830_crtc_dpms() Otherwise, the changes may not have taken effect. --- src/i830_display.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/i830_display.c b/src/i830_display.c index f05b5c73..f0aac15c 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -487,6 +487,7 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mode) int pipe = intel_crtc->pipe; int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; + int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE; int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; CARD32 temp; @@ -512,6 +513,9 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mode) temp = INREG(dspcntr_reg); 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); break; @@ -526,6 +530,9 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mode) /* Disable the VGA plane that we never use */ OUTREG(VGACNTRL, VGA_DISP_DISABLE); + /* Flush the plane changes */ + OUTREG(dspbase_reg, INREG(dspbase_reg)); + if (!IS_I9XX(pI830)) { /* Wait for vblank for the disable to take effect */ i830WaitForVblank(pScrn); From 7ed1b05922c07ff45a5794a992fd3d59ab55aa73 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 12 Dec 2006 16:03:52 -0800 Subject: [PATCH 13/32] Fix mac mini SDVO output: write the SDVO[BC] enabled register state twice. --- src/i830_sdvo.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index 7936abdf..895639eb 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -696,6 +696,12 @@ i830_sdvo_dpms(xf86OutputPtr output, int mode) i830_sdvo_set_active_outputs(output, dev_priv->active_outputs); + /* 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); + for (i = 0; i < 2; i++) i830WaitForVblank(pScrn); From 41444183b59ed84c09749ca89afbef036d42ec5f Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 12 Dec 2006 18:08:57 -0800 Subject: [PATCH 14/32] Replace custom, partially broken DPMS implementation with a generic one. --- src/i830_display.c | 6 +++++ src/i830_driver.c | 53 +-------------------------------------------- src/i830_xf86Crtc.c | 35 ++++++++++++++++++++++++++++++ src/i830_xf86Crtc.h | 3 +++ 4 files changed, 45 insertions(+), 52 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index f0aac15c..8da51313 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -478,6 +478,12 @@ i830PipeInUse (xf86CrtcPtr crtc) return FALSE; } +/** + * 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) { diff --git a/src/i830_driver.c b/src/i830_driver.c index d8a9c9bc..7ec5559f 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -314,8 +314,6 @@ const char *i830_output_type_names[] = { "TVOUT", }; -static void I830DisplayPowerManagementSet(ScrnInfoPtr pScrn, - int PowerManagementMode, int flags); static void i830AdjustFrame(int scrnIndex, int x, int y, int flags); static Bool I830CloseScreen(int scrnIndex, ScreenPtr pScreen); static Bool I830SaveScreen(ScreenPtr pScreen, int unblack); @@ -2863,7 +2861,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) return FALSE; } - xf86DPMSInit(pScreen, I830DisplayPowerManagementSet, 0); + xf86DPMSInit(pScreen, xf86DPMSSet, 0); #ifdef I830_XV /* Init video */ @@ -3319,55 +3317,6 @@ I830SaveScreen(ScreenPtr pScreen, int mode) return TRUE; } -/* Use the VBE version when available. */ -static void -I830DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, - int flags) -{ - I830Ptr pI830 = I830PTR(pScrn); - int i; - CARD32 temp, ctrl, base; - - for (i = 0; i < pI830->xf86_config.num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; - - (*output->funcs->dpms) (output, PowerManagementMode); - } - - for (i = 0; i < pI830->xf86_config.num_crtc; i++) - { - xf86CrtcPtr crtc = pI830->xf86_config.crtc[i]; - - if (i == 0) { - ctrl = DSPACNTR; - base = DSPABASE; - } else { - ctrl = DSPBCNTR; - base = DSPBADDR; - } - /* XXX pipe disable too? */ - if (crtc->enabled) { - temp = INREG(ctrl); - if (PowerManagementMode == DPMSModeOn) - temp |= DISPLAY_PLANE_ENABLE; - else - temp &= ~DISPLAY_PLANE_ENABLE; - OUTREG(ctrl, temp); - /* Flush changes */ - temp = INREG(base); - OUTREG(base, temp); - } - } - - if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) { - if (PowerManagementMode == DPMSModeOn) - pI830->CursorInfoRec->ShowCursor(pScrn); - else - pI830->CursorInfoRec->HideCursor(pScrn); - pI830->cursorOn = TRUE; - } -} - static Bool I830CloseScreen(int scrnIndex, ScreenPtr pScreen) { diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c index 448d4f94..a222382d 100644 --- a/src/i830_xf86Crtc.c +++ b/src/i830_xf86Crtc.c @@ -590,3 +590,38 @@ xf86InitialConfiguration (ScrnInfoPtr pScrn) xfree (modes); return TRUE; } + +/** + * Set the DPMS power mode of all outputs and CRTCs. + * + * If the new mode is off, it will turn off outputs and then CRTCs. + * Otherwise, it will affect CRTCs before outputs. + */ +void +xf86DPMSSet(ScrnInfoPtr pScrn, int mode, int flags) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; + + if (mode == DPMSModeOff) { + for (i = 0; i < config->num_output; i++) { + xf86OutputPtr output = config->output[i]; + if (output->crtc != NULL) + (*output->funcs->dpms) (output, mode); + } + } + + for (i = 0; i < config->num_crtc; i++) { + xf86CrtcPtr crtc = config->crtc[i]; + if (crtc->enabled) + (*crtc->funcs->dpms) (crtc, mode); + } + + if (mode != DPMSModeOff) { + for (i = 0; i < config->num_output; i++) { + xf86OutputPtr output = config->output[i]; + if (output->crtc != NULL) + (*output->funcs->dpms) (output, mode); + } + } +} diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h index 21fc244e..042cb2f0 100644 --- a/src/i830_xf86Crtc.h +++ b/src/i830_xf86Crtc.h @@ -378,4 +378,7 @@ xf86SetScrnInfoModes (ScrnInfoPtr pScrn); Bool xf86InitialConfiguration (ScrnInfoPtr pScrn); +void +xf86DPMSSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags); + #endif /* _XF86CRTC_H_ */ From 63bf48481d4e5e285fdfe7037ea4150283163a54 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 12 Dec 2006 22:42:41 -0800 Subject: [PATCH 15/32] Correct typo in mac mini hack, and return modes when the hack is unnecessary. --- src/i830_sdvo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index 895639eb..68ee9414 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -1003,7 +1003,7 @@ i830_sdvo_get_modes(xf86OutputPtr output) modes = i830_ddc_get_modes(output); if (modes != NULL) - return NULL; + return modes; /* Mac mini hack. On this device, I get DDC through the analog, which * load-detects as disconnected. I fail to DDC through the SDVO DDC, From d57a25815398ae83eae8bdcb3a1b607760aa30b6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 12 Dec 2006 22:48:21 -0800 Subject: [PATCH 16/32] Elide duplicate modes in pScrn->monitor. xf86DDCMonitorSet dumps all of the DDC-discovered modes into the monitor mode list without checking to see if they are already present. This provides an ever-changing list of modes for outputs which have no DDC and which simply duplicate the monitor mode list. --- src/i830_xf86Crtc.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c index a222382d..6f96d448 100644 --- a/src/i830_xf86Crtc.c +++ b/src/i830_xf86Crtc.c @@ -337,6 +337,30 @@ xf86DefaultScreenLimits (ScrnInfoPtr pScrn, int *widthp, int *heightp) *heightp = height; } +/* + * XXX walk the monitor mode list and prune out duplicates that + * are inserted by xf86DDCMonitorSet. In an ideal world, that + * function would do this work by itself. + */ + +static void +xf86PruneDuplicateMonitorModes (MonPtr Monitor) +{ + DisplayModePtr master, clone, next; + + for (master = Monitor->Modes; + master && master != Monitor->Last; + master = master->next) + { + for (clone = master->next; clone && clone != Monitor->Modes; clone = next) + { + next = clone->next; + if (xf86ModesEqual (master, clone)) + xf86DeleteMode (&Monitor->Modes, clone); + } + } +} + void xf86ProbeOutputModes (ScrnInfoPtr pScrn) { @@ -344,6 +368,9 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn) Bool properties_set = FALSE; int o; + /* Elide duplicate modes before defaulting code uses them */ + xf86PruneDuplicateMonitorModes (pScrn->monitor); + /* Probe the list of modes for each output. */ for (o = 0; o < config->num_output; o++) { From 4cdcaac26b3f425ec8fcc2fd3eaa9bfb7a137422 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 12 Dec 2006 23:26:00 -0800 Subject: [PATCH 17/32] Write dpll_md register while updating dpll as that appears to be required. SDVO multiplier on 965 is in the dpll_md register; for some reason, that needs to be written along with the dpll value or the multiplier doesn't get set correctly. --- src/i830_display.c | 8 +++----- src/i830_sdvo.c | 4 +--- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index 8da51313..e4d8e9f3 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -752,11 +752,9 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, OUTREG(fp_reg, fp); OUTREG(dpll_reg, dpll); if (IS_I965G(pI830)) { - /* Set the SDVO multiplier/divider to 1x for the sake of analog output. - * It will be updated by the SDVO code if SDVO had fixed up the clock - * for a higher multiplier. - */ - OUTREG(dpll_md_reg, 0); + 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)); } OUTREG(htot_reg, (adjusted_mode->CrtcHDisplay - 1) | diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index 68ee9414..da4df925 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -557,7 +557,6 @@ i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode, xf86CrtcPtr crtc = output->crtc; I830CrtcPrivatePtr intel_crtc = crtc->driver_private; CARD32 sdvox; - int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD; int sdvo_pixel_multiply; CARD16 width, height; CARD16 h_blank_len, h_sync_len, v_blank_len, v_sync_len; @@ -663,8 +662,7 @@ i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode, sdvo_pixel_multiply = i830_sdvo_get_pixel_multiplier(mode); if (IS_I965G(pI830)) { - OUTREG(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) | - ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT)); + /* done in crtc_mode_set as the dpll_md reg must be written early */ } else if (IS_I945G(pI830) || IS_I945GM(pI830)) { /* done in crtc_mode_set as it lives inside the dpll register */ } else { From df0a5a25aa72563a33731f8063602dd7faad8459 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 13 Dec 2006 11:38:18 -0800 Subject: [PATCH 18/32] Rename outputs to TMDS-1/TMDS-2, LVDS, TV and VGA. These names are reasonably short and describe the connector rather than the target media, but we don't appear to have any way to determine what is on the other end of the wire. More importantly, they're all unique now. --- src/i830_dvo.c | 2 +- src/i830_lvds.c | 2 +- src/i830_sdvo.c | 10 ++++++++++ src/i830_xf86Crtc.c | 17 +++++++++++++++++ src/i830_xf86Crtc.h | 3 +++ 5 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/i830_dvo.c b/src/i830_dvo.c index 25ced639..ed8d1c74 100644 --- a/src/i830_dvo.c +++ b/src/i830_dvo.c @@ -246,7 +246,7 @@ i830_dvo_init(ScrnInfoPtr pScrn) int ret; output = xf86OutputCreate (pScrn, &i830_dvo_output_funcs, - "ADD AGP card"); + "TMDS"); if (!output) return; intel_output = xnfcalloc (sizeof (I830OutputPrivateRec), 1); diff --git a/src/i830_lvds.c b/src/i830_lvds.c index 90f785e9..4027a256 100644 --- a/src/i830_lvds.c +++ b/src/i830_lvds.c @@ -311,7 +311,7 @@ i830_lvds_init(ScrnInfoPtr pScrn) } } - output = xf86OutputCreate (pScrn, &i830_lvds_output_funcs, "Built-in LCD panel"); + output = xf86OutputCreate (pScrn, &i830_lvds_output_funcs, "LVDS"); if (!output) return; intel_output = xnfcalloc (sizeof (I830OutputPrivateRec), 1); diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index da4df925..90a62c00 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -1053,6 +1053,9 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) int i; unsigned char ch[0x40]; I2CBusPtr i2cbus = NULL, ddcbus; + char name[60]; + char *name_prefix; + char *name_suffix; output = xf86OutputCreate (pScrn, &i830_sdvo_output_funcs, "ADD2 PCIE card"); @@ -1087,9 +1090,11 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) if (output_device == SDVOB) { dev_priv->d.DevName = "SDVO Controller B"; dev_priv->d.SlaveAddr = 0x70; + name_suffix="-1"; } else { dev_priv->d.DevName = "SDVO Controller C"; dev_priv->d.SlaveAddr = 0x72; + name_suffix="-2"; } dev_priv->d.pI2CBus = i2cbus; dev_priv->d.DriverPrivate.ptr = output; @@ -1158,11 +1163,13 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) { dev_priv->active_outputs = SDVO_OUTPUT_TMDS0; output->subpixel_order = SubPixelHorizontalRGB; + name_prefix="TMDS"; } else if (dev_priv->caps.output_flags & SDVO_OUTPUT_TMDS1) { dev_priv->active_outputs = SDVO_OUTPUT_TMDS1; output->subpixel_order = SubPixelHorizontalRGB; + name_prefix="TMDS"; } else { @@ -1174,6 +1181,9 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) SDVO_NAME(dev_priv), bytes[0], bytes[1]); } + strcpy (name, name_prefix); + strcat (name, name_suffix); + xf86OutputRename (output, name); /* Set the input timing to the screen. Assume always input 0. */ i830_sdvo_set_target_input(output, TRUE, FALSE); diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c index 6f96d448..25657e65 100644 --- a/src/i830_xf86Crtc.c +++ b/src/i830_xf86Crtc.c @@ -104,6 +104,21 @@ xf86OutputCreate (ScrnInfoPtr scrn, return output; } +void +xf86OutputRename (xf86OutputPtr output, const char *name) +{ + int len = strlen(name); + char *newname = xalloc (len + 1); + + if (!newname) + return; /* so sorry... */ + + strcpy (newname, name); + if (output->name != (char *) (output + 1)) + xfree (output->name); + output->name = newname; +} + void xf86OutputDestroy (xf86OutputPtr output) { @@ -123,6 +138,8 @@ xf86OutputDestroy (xf86OutputPtr output) xf86_config->num_output--; break; } + if (output->name != (char *) (output + 1)) + xfree (output->name); xfree (output); } diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h index 042cb2f0..f2c2429f 100644 --- a/src/i830_xf86Crtc.h +++ b/src/i830_xf86Crtc.h @@ -366,6 +366,9 @@ xf86OutputCreate (ScrnInfoPtr scrn, const xf86OutputFuncsRec *funcs, const char *name); +void +xf86OutputRename (xf86OutputPtr output, const char *name); + void xf86OutputDestroy (xf86OutputPtr output); From e27372e85a007d8a7e31678dbdb62755c22918bf Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 13 Dec 2006 00:26:27 -0800 Subject: [PATCH 19/32] Add some caution with PCI write posting and DPLL delays to i830_crtc_dpms. While it doesn't specifically help/hurt my test case, we've seen enough mysterious behavior that caution is probably warranted. --- src/i830_display.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/i830_display.c b/src/i830_display.c index e4d8e9f3..c111145e 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -507,6 +507,7 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mode) /* Enable the DPLL */ temp = INREG(dpll_reg); OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE); + (void)INREG(dpll_reg); /* write posting */ /* Wait for the clocks to stabilize. */ usleep(150); @@ -538,6 +539,7 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mode) /* Flush the plane changes */ OUTREG(dspbase_reg, INREG(dspbase_reg)); + (void)INREG(dspbase_reg); /* write posting */ if (!IS_I9XX(pI830)) { /* Wait for vblank for the disable to take effect */ @@ -547,12 +549,17 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mode) /* Next, disable display pipes */ temp = INREG(pipeconf_reg); OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE); + (void)INREG(pipeconf_reg); /* write posting */ /* 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 */ + + /* Wait for the clocks to turn off. */ + usleep(150); break; } } From 3fa5b3998353518c40e2fb0c28b425ee22c8d625 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 13 Dec 2006 11:54:36 -0800 Subject: [PATCH 20/32] Add magic double-write of the dpll register to fix mac mini cold boot. --- src/i830_display.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/i830_display.c b/src/i830_display.c index c111145e..37a6e32e 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -758,6 +758,15 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, OUTREG(fp_reg, fp); OUTREG(dpll_reg, dpll); + + /* 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 + * INREG for presumable pci write posting magic before and after the dpll + * 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) | From 001e272437a0247ffbc4b9ff8a3f2b437cf4c533 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 13 Dec 2006 12:08:58 -0800 Subject: [PATCH 21/32] Auto-detect working TV output by checking TV regs functionality. We can't figure out which chips are supposed to have TV out, so instead we prod the TV_DAC register to see if it will hold the value written to it, if not, we assume the chip doesn't have TV out. --- src/i830_tv.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/src/i830_tv.c b/src/i830_tv.c index b6cc2c9b..42c2aadd 100644 --- a/src/i830_tv.c +++ b/src/i830_tv.c @@ -583,8 +583,11 @@ i830_tv_detect_type (xf86CrtcPtr crtc, tv_dac |= (TVDAC_STATE_CHG_EN | TVDAC_A_SENSE_CTL | TVDAC_B_SENSE_CTL | - TVDAC_C_SENSE_CTL); - tv_dac = DAC_CTL_OVERRIDE | DAC_A_0_7_V | DAC_B_0_7_V | DAC_C_0_7_V; + TVDAC_C_SENSE_CTL | + DAC_CTL_OVERRIDE | + DAC_A_0_7_V | + DAC_B_0_7_V | + DAC_C_0_7_V); OUTREG(TV_CTL, tv_ctl); OUTREG(TV_DAC, tv_dac); i830WaitForVblank(pScrn); @@ -612,7 +615,7 @@ i830_tv_detect_type (xf86CrtcPtr crtc, type = TV_TYPE_COMPONENT; } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Couldn't detect TV connection\n"); + "No TV connection detected\n"); type = TV_TYPE_NONE; } @@ -730,10 +733,34 @@ i830_tv_init(ScrnInfoPtr pScrn) xf86OutputPtr output; I830OutputPrivatePtr intel_output; struct i830_tv_priv *dev_priv; + CARD32 tv_dac_on, tv_dac_off, save_tv_dac; if ((INREG(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED) return; + /* + * Sanity check the TV output by checking to see if the + * DAC register holds a value + */ + save_tv_dac = INREG(TV_DAC); + + OUTREG(TV_DAC, save_tv_dac | TVDAC_STATE_CHG_EN); + tv_dac_on = INREG(TV_DAC); + + OUTREG(TV_DAC, save_tv_dac & ~TVDAC_STATE_CHG_EN); + tv_dac_off = INREG(TV_DAC); + + OUTREG(TV_DAC, save_tv_dac); + + /* + * If the register does not hold the state change enable + * bit, (either as a 0 or a 1), assume it doesn't really + * exist + */ + if ((tv_dac_on & TVDAC_STATE_CHG_EN) == 0 || + (tv_dac_off & TVDAC_STATE_CHG_EN) != 0) + return; + output = xf86OutputCreate (pScrn, &i830_tv_output_funcs, "TV"); if (!output) From 3fe802453a85183a69c36a098639895f49b17df1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 13 Dec 2006 13:15:14 -0800 Subject: [PATCH 22/32] Move xf86CrtcConfig to ScrnInfo private. Pull xf86CrtcConfig out of the driver private structure and allocate a ScrnInfo private index for it. Also, make the arrays of outputs and crtcs dynamic instead of fixed. --- src/i830.h | 3 -- src/i830_cursor.c | 34 +++++++++++++--------- src/i830_display.c | 70 +++++++++++++++++++++++---------------------- src/i830_dri.c | 3 +- src/i830_driver.c | 50 +++++++++++++++++++------------- src/i830_lvds.c | 5 ++-- src/i830_randr.c | 33 +++++++++++++++++---- src/i830_sdvo.c | 10 +++---- src/i830_tv.c | 6 ++-- src/i830_video.c | 3 +- src/i830_xf86Crtc.c | 56 ++++++++++++++++++++++++++++++++++-- src/i830_xf86Crtc.h | 47 +++++++++++++++++++----------- 12 files changed, 212 insertions(+), 108 deletions(-) diff --git a/src/i830.h b/src/i830.h index 292374c1..a92f557e 100644 --- a/src/i830.h +++ b/src/i830.h @@ -234,9 +234,6 @@ typedef struct _I830PipeRec { } I830PipeRec, *I830PipePtr; typedef struct _I830Rec { - /* Must be first */ - xf86CrtcConfigRec xf86_config; - unsigned char *MMIOBase; unsigned char *FbBase; int cpp; diff --git a/src/i830_cursor.c b/src/i830_cursor.c index e9ca8f15..cb1585fb 100644 --- a/src/i830_cursor.c +++ b/src/i830_cursor.c @@ -86,10 +86,11 @@ I830SetPipeCursorBase (xf86CrtcPtr crtc) I830CrtcPrivatePtr intel_crtc = crtc->driver_private; int pipe = intel_crtc->pipe; I830Ptr pI830 = I830PTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); int cursor_base = (pipe == 0 ? CURSOR_A_BASE : CURSOR_B_BASE); I830MemRange *cursor_mem; - if (pipe >= pI830->xf86_config.num_crtc) + if (pipe >= xf86_config->num_crtc) FatalError("Bad pipe number for cursor base setting\n"); if (pI830->CursorIsARGB) @@ -180,17 +181,18 @@ I830SetPipeCursor (xf86CrtcPtr crtc, Bool force) void I830InitHWCursor(ScrnInfoPtr pScrn) { + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); CARD32 temp; int i; DPRINTF(PFX, "I830InitHWCursor\n"); - for (i = 0; i < pI830->xf86_config.num_crtc; i++) - pI830->xf86_config.crtc[i]->cursorShown = FALSE; + for (i = 0; i < xf86_config->num_crtc; i++) + xf86_config->crtc[i]->cursorShown = FALSE; /* Initialise the HW cursor registers, leaving the cursor hidden. */ if (IS_MOBILE(pI830) || IS_I9XX(pI830)) { - for (i = 0; i < pI830->xf86_config.num_crtc; i++) + for (i = 0; i < xf86_config->num_crtc; i++) { int cursor_control = i == 0 ? CURSOR_A_CONTROL : CURSOR_B_CONTROL; temp = INREG(cursor_control); @@ -204,7 +206,7 @@ I830InitHWCursor(ScrnInfoPtr pScrn) temp |= CURSOR_MODE_64_4C_AX; /* Need to set control, then address. */ OUTREG(cursor_control, temp); - I830SetPipeCursorBase(pI830->xf86_config.crtc[i]); + I830SetPipeCursorBase(xf86_config->crtc[i]); } } else { temp = INREG(CURSOR_CONTROL); @@ -217,7 +219,7 @@ I830InitHWCursor(ScrnInfoPtr pScrn) /* This initialises the format and leave the cursor disabled. */ OUTREG(CURSOR_CONTROL, temp); /* Need to set address and size after disabling. */ - I830SetPipeCursorBase(pI830->xf86_config.crtc[0]); + I830SetPipeCursorBase(xf86_config->crtc[0]); temp = ((I810_CURSOR_X & CURSOR_SIZE_MASK) << CURSOR_SIZE_HSHIFT) | ((I810_CURSOR_Y & CURSOR_SIZE_MASK) << CURSOR_SIZE_VSHIFT); OUTREG(CURSOR_SIZE, temp); @@ -454,6 +456,7 @@ static void I830LoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs) static void I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) { + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); CARD32 temp; Bool inrange; @@ -490,9 +493,9 @@ I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) x -= hotspotx; y -= hotspoty; - for (pipe = 0; pipe < pI830->xf86_config.num_crtc; pipe++) + for (pipe = 0; pipe < xf86_config->num_crtc; pipe++) { - xf86CrtcPtr crtc = pI830->xf86_config.crtc[pipe]; + xf86CrtcPtr crtc = xf86_config->crtc[pipe]; DisplayModePtr mode = &crtc->curMode; int thisx = x - crtc->x; int thisy = y - crtc->y; @@ -542,6 +545,7 @@ I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) static void I830ShowCursor(ScrnInfoPtr pScrn) { + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); int pipe; @@ -556,26 +560,28 @@ I830ShowCursor(ScrnInfoPtr pScrn) pI830->CursorMemARGB->Physical, pI830->CursorMemARGB->Start); pI830->cursorOn = TRUE; - for (pipe = 0; pipe < pI830->xf86_config.num_crtc; pipe++) - I830SetPipeCursor (pI830->xf86_config.crtc[pipe], TRUE); + for (pipe = 0; pipe < xf86_config->num_crtc; pipe++) + I830SetPipeCursor (xf86_config->crtc[pipe], TRUE); } static void I830HideCursor(ScrnInfoPtr pScrn) { + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); int pipe; DPRINTF(PFX, "I830HideCursor\n"); pI830->cursorOn = FALSE; - for (pipe = 0; pipe < pI830->xf86_config.num_crtc; pipe++) - I830SetPipeCursor (pI830->xf86_config.crtc[pipe], TRUE); + for (pipe = 0; pipe < xf86_config->num_crtc; pipe++) + I830SetPipeCursor (xf86_config->crtc[pipe], TRUE); } static void I830SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) { + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); int pipe; @@ -587,9 +593,9 @@ I830SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) DPRINTF(PFX, "I830SetCursorColors\n"); - for (pipe = 0; pipe < pI830->xf86_config.num_crtc; pipe++) + for (pipe = 0; pipe < xf86_config->num_crtc; pipe++) { - xf86CrtcPtr crtc = pI830->xf86_config.crtc[pipe]; + xf86CrtcPtr crtc = xf86_config->crtc[pipe]; int pal0 = pipe == 0 ? CURSOR_A_PALETTE0 : CURSOR_B_PALETTE0; if (crtc->enabled) diff --git a/src/i830_display.c b/src/i830_display.c index 37a6e32e..4a429fc1 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -225,12 +225,12 @@ Bool i830PipeHasType (xf86CrtcPtr crtc, int type) { ScrnInfoPtr pScrn = crtc->scrn; - I830Ptr pI830 = I830PTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); int i; - for (i = 0; i < pI830->xf86_config.num_output; i++) + for (i = 0; i < xf86_config->num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; + xf86OutputPtr output = xf86_config->output[i]; if (output->crtc == crtc) { I830OutputPrivatePtr intel_output = output->driver_private; @@ -373,14 +373,14 @@ DisplayModePtr i830PipeFindClosestMode(xf86CrtcPtr crtc, DisplayModePtr pMode) { ScrnInfoPtr pScrn = crtc->scrn; - I830Ptr pI830 = I830PTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); DisplayModePtr pBest = NULL, pScan = NULL; int i; /* Assume that there's only one output connected to the given CRTC. */ - for (i = 0; i < pI830->xf86_config.num_output; i++) + for (i = 0; i < xf86_config->num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; + xf86OutputPtr output = xf86_config->output[i]; if (output->crtc == crtc && output->probed_modes != NULL) { pScan = output->probed_modes; @@ -469,11 +469,11 @@ Bool i830PipeInUse (xf86CrtcPtr crtc) { ScrnInfoPtr pScrn = crtc->scrn; - I830Ptr pI830 = I830PTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); int i; - for (i = 0; i < pI830->xf86_config.num_output; i++) - if (pI830->xf86_config.output[i]->crtc == crtc) + for (i = 0; i < xf86_config->num_output; i++) + if (xf86_config->output[i]->crtc == crtc) return TRUE; return FALSE; } @@ -584,6 +584,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModePtr adjusted_mode) { ScrnInfoPtr pScrn = crtc->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); I830CrtcPrivatePtr intel_crtc = crtc->driver_private; int pipe = intel_crtc->pipe; @@ -612,8 +613,8 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, /* Set up some convenient bools for what outputs are connected to * our pipe, used in DPLL setup. */ - for (i = 0; i < pI830->xf86_config.num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; I830OutputPrivatePtr intel_output = output->driver_private; if (output->crtc != crtc) @@ -814,7 +815,7 @@ i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode, Bool plane_enable) { ScrnInfoPtr pScrn = crtc->scrn; - I830Ptr pI830 = I830PTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); int i; Bool ret = FALSE; #ifdef XF86DRI @@ -842,8 +843,8 @@ i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode, * adjust it according to limitations or output properties, and also * a chance to reject the mode entirely. */ - for (i = 0; i < pI830->xf86_config.num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; if (output->crtc != crtc) continue; @@ -860,8 +861,8 @@ i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode, } /* Disable the outputs and CRTCs before setting the mode. */ - for (i = 0; i < pI830->xf86_config.num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; if (output->crtc != crtc) continue; @@ -876,16 +877,16 @@ i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode, * on the DPLL. */ crtc->funcs->mode_set(crtc, pMode, adjusted_mode); - for (i = 0; i < pI830->xf86_config.num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; if (output->crtc == crtc) output->funcs->mode_set(output, pMode, adjusted_mode); } /* Now, enable the clocks, plane, pipe, and outputs that we set up. */ crtc->funcs->dpms(crtc, DPMSModeOn); - for (i = 0; i < pI830->xf86_config.num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; if (output->crtc == crtc) output->funcs->dpms(output, DPMSModeOn); } @@ -923,14 +924,15 @@ done: void i830DisableUnusedFunctions(ScrnInfoPtr pScrn) { + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); int o, pipe; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling unused functions\n"); - for (o = 0; o < pI830->xf86_config.num_output; o++) + for (o = 0; o < xf86_config->num_output; o++) { - xf86OutputPtr output = pI830->xf86_config.output[o]; + xf86OutputPtr output = xf86_config->output[o]; if (!output->crtc) (*output->funcs->dpms)(output, DPMSModeOff); } @@ -939,9 +941,9 @@ i830DisableUnusedFunctions(ScrnInfoPtr pScrn) * internal TV) should have no outputs trying to pull data out of it, so * we're ready to turn those off. */ - for (pipe = 0; pipe < pI830->xf86_config.num_crtc; pipe++) + for (pipe = 0; pipe < xf86_config->num_crtc; pipe++) { - xf86CrtcPtr crtc = pI830->xf86_config.crtc[pipe]; + xf86CrtcPtr crtc = xf86_config->crtc[pipe]; I830CrtcPrivatePtr intel_crtc = crtc->driver_private; int pipe = intel_crtc->pipe; int dspcntr_reg = pipe == 0 ? DSPACNTR : DSPBCNTR; @@ -990,7 +992,6 @@ Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) { xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - I830Ptr pI830 = I830PTR(pScrn); Bool ok = TRUE; xf86CrtcPtr crtc = config->output[config->compat_output]->crtc; @@ -1025,13 +1026,14 @@ done: void i830DescribeOutputConfiguration(ScrnInfoPtr pScrn) { + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); int i; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output configuration:\n"); - for (i = 0; i < pI830->xf86_config.num_crtc; i++) { - xf86CrtcPtr crtc = pI830->xf86_config.crtc[i]; + for (i = 0; i < xf86_config->num_crtc; i++) { + xf86CrtcPtr crtc = xf86_config->crtc[i]; CARD32 dspcntr = INREG(DSPACNTR + (DSPBCNTR - DSPACNTR) * i); CARD32 pipeconf = INREG(PIPEACONF + (PIPEBCONF - PIPEACONF) * i); Bool hw_plane_enable = (dspcntr & DISPLAY_PLANE_ENABLE) != 0; @@ -1061,8 +1063,8 @@ i830DescribeOutputConfiguration(ScrnInfoPtr pScrn) } } - for (i = 0; i < pI830->xf86_config.num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; xf86CrtcPtr crtc = output->crtc; I830CrtcPrivatePtr intel_crtc = crtc ? crtc->driver_private : NULL; @@ -1091,7 +1093,7 @@ xf86CrtcPtr i830GetLoadDetectPipe(xf86OutputPtr output) { ScrnInfoPtr pScrn = output->scrn; - I830Ptr pI830 = I830PTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830OutputPrivatePtr intel_output = output->driver_private; xf86CrtcPtr crtc; int i; @@ -1099,14 +1101,14 @@ i830GetLoadDetectPipe(xf86OutputPtr output) if (output->crtc) return output->crtc; - for (i = 0; i < pI830->xf86_config.num_crtc; i++) - if (!i830PipeInUse(pI830->xf86_config.crtc[i])) + for (i = 0; i < xf86_config->num_crtc; i++) + if (!i830PipeInUse(xf86_config->crtc[i])) break; - if (i == pI830->xf86_config.num_crtc) + if (i == xf86_config->num_crtc) return NULL; - crtc = pI830->xf86_config.crtc[i]; + crtc = xf86_config->crtc[i]; output->crtc = crtc; intel_output->load_detect_temp = TRUE; diff --git a/src/i830_dri.c b/src/i830_dri.c index 0f6145b2..c5d7a94e 100644 --- a/src/i830_dri.c +++ b/src/i830_dri.c @@ -1518,11 +1518,12 @@ Bool I830DRISetVBlankInterrupt (ScrnInfoPtr pScrn, Bool on) { I830Ptr pI830 = I830PTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); drmI830VBlankPipe pipe; if (pI830->directRenderingEnabled && pI830->drmMinor >= 5) { if (on) { - if (pI830->xf86_config.num_crtc > 1 && pI830->xf86_config.crtc[1]->enabled) + if (xf86_config->num_crtc > 1 && xf86_config->crtc[1]->enabled) pipe.pipe = DRM_I830_VBLANK_PIPE_B; else pipe.pipe = DRM_I830_VBLANK_PIPE_A; diff --git a/src/i830_driver.c b/src/i830_driver.c index 7ec5559f..d4f2aa37 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -578,6 +578,7 @@ static void I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO * colors, VisualPtr pVisual) { + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830; int i,j, index; unsigned char r, g, b; @@ -589,9 +590,9 @@ I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, DPRINTF(PFX, "I830LoadPalette: numColors: %d\n", numColors); pI830 = I830PTR(pScrn); - for(p=0; p < pI830->xf86_config.num_crtc; p++) + for(p=0; p < xf86_config->num_crtc; p++) { - xf86CrtcPtr crtc = pI830->xf86_config.crtc[p]; + xf86CrtcPtr crtc = xf86_config->crtc[p]; I830CrtcPrivatePtr intel_crtc = crtc->driver_private; if (p == 0) { @@ -896,6 +897,7 @@ I830ReduceMMSize(ScrnInfoPtr pScrn, unsigned long newSize, static Bool I830PreInit(ScrnInfoPtr pScrn, int flags) { + xf86CrtcConfigPtr xf86_config; vgaHWPtr hwp; I830Ptr pI830; MessageType from = X_PROBED; @@ -968,6 +970,10 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) } else pI830->entityPrivate = NULL; + /* Allocate an xf86CrtcConfig */ + xf86CrtcConfigInit (pScrn); + xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + if (xf86RegisterResources(pI830->pEnt->index, 0, ResNone)) { PreInitCleanup(pScrn); return FALSE; @@ -1386,9 +1392,9 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) * This will give us some likely legitimate response for later if both * pipes are already allocated and we're asked to do a detect. */ - for (i = 0; i < pI830->xf86_config.num_output; i++) + for (i = 0; i < xf86_config->num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; + xf86OutputPtr output = xf86_config->output[i]; output->status = (*output->funcs->detect) (output); } @@ -2096,6 +2102,7 @@ SetHWOperatingState(ScrnInfoPtr pScrn) static Bool SaveHWState(ScrnInfoPtr pScrn) { + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); vgaHWPtr hwp = VGAHWPTR(pScrn); vgaRegPtr vgaReg = &hwp->SavedReg; @@ -2125,7 +2132,7 @@ SaveHWState(ScrnInfoPtr pScrn) pI830->savePaletteA[i] = INREG(PALETTE_A + (i << 2)); } - if(pI830->xf86_config.num_crtc == 2) { + if(xf86_config->num_crtc == 2) { pI830->savePIPEBCONF = INREG(PIPEBCONF); pI830->savePIPEBSRC = INREG(PIPEBSRC); pI830->saveDSPBCNTR = INREG(DSPBCNTR); @@ -2169,8 +2176,8 @@ SaveHWState(ScrnInfoPtr pScrn) pI830->savePFIT_CONTROL = INREG(PFIT_CONTROL); - for (i = 0; i < pI830->xf86_config.num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; if (output->funcs->save) (*output->funcs->save) (output); } @@ -2184,6 +2191,7 @@ SaveHWState(ScrnInfoPtr pScrn) static Bool RestoreHWState(ScrnInfoPtr pScrn) { + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); vgaHWPtr hwp = VGAHWPTR(pScrn); vgaRegPtr vgaReg = &hwp->SavedReg; @@ -2196,14 +2204,14 @@ RestoreHWState(ScrnInfoPtr pScrn) #endif /* Disable outputs */ - for (i = 0; i < pI830->xf86_config.num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; output->funcs->dpms(output, DPMSModeOff); } /* Disable pipes */ - for (i = 0; i < pI830->xf86_config.num_crtc; i++) { - xf86CrtcPtr crtc = pI830->xf86_config.crtc[i]; + for (i = 0; i < xf86_config->num_crtc; i++) { + xf86CrtcPtr crtc = xf86_config->crtc[i]; crtc->funcs->dpms(crtc, DPMSModeOff); } @@ -2212,7 +2220,7 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(DPLL_A, pI830->saveDPLL_A); if (IS_I965G(pI830)) OUTREG(DPLL_A_MD, pI830->saveDPLL_A_MD); - if(pI830->xf86_config.num_crtc == 2) { + if(xf86_config->num_crtc == 2) { OUTREG(FPB0, pI830->saveFPB0); OUTREG(FPB1, pI830->saveFPB1); OUTREG(DPLL_B, pI830->saveDPLL_B); @@ -2237,7 +2245,7 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(PALETTE_A + (i << 2), pI830->savePaletteA[i]); } - if(pI830->xf86_config.num_crtc == 2) { + if(xf86_config->num_crtc == 2) { OUTREG(HTOTAL_B, pI830->saveHTOTAL_B); OUTREG(HBLANK_B, pI830->saveHBLANK_B); OUTREG(HSYNC_B, pI830->saveHSYNC_B); @@ -2273,8 +2281,8 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(DSPACNTR, pI830->saveDSPACNTR); OUTREG(DSPBCNTR, pI830->saveDSPBCNTR); - for (i = 0; i < pI830->xf86_config.num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; (*output->funcs->restore) (output); } @@ -3097,6 +3105,7 @@ static Bool I830EnterVT(int scrnIndex, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); int i; @@ -3131,9 +3140,9 @@ I830EnterVT(int scrnIndex, int flags) ResetState(pScrn, FALSE); SetHWOperatingState(pScrn); - for (i = 0; i < pI830->xf86_config.num_crtc; i++) + for (i = 0; i < xf86_config->num_crtc; i++) { - xf86CrtcPtr crtc = pI830->xf86_config.crtc[i]; + xf86CrtcPtr crtc = xf86_config->crtc[i]; /* Mark that we'll need to re-set the mode for sure */ memset(&crtc->curMode, 0, sizeof(crtc->curMode)); @@ -3271,6 +3280,7 @@ static Bool I830SaveScreen(ScreenPtr pScreen, int mode) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); Bool on = xf86IsUnblank(mode); CARD32 temp, ctrl, base, surf; @@ -3279,7 +3289,7 @@ I830SaveScreen(ScreenPtr pScreen, int mode) DPRINTF(PFX, "I830SaveScreen: %d, on is %s\n", mode, BOOLTOSTRING(on)); if (pScrn->vtSema) { - for (i = 0; i < pI830->xf86_config.num_crtc; i++) { + for (i = 0; i < xf86_config->num_crtc; i++) { if (i == 0) { ctrl = DSPACNTR; base = DSPABASE; @@ -3289,7 +3299,7 @@ I830SaveScreen(ScreenPtr pScreen, int mode) base = DSPBADDR; surf = DSPBSURF; } - if (pI830->xf86_config.crtc[i]->enabled) { + if (xf86_config->crtc[i]->enabled) { temp = INREG(ctrl); if (on) temp |= DISPLAY_PLANE_ENABLE; @@ -3508,7 +3518,7 @@ i830MonitorDetectDebugger(ScrnInfoPtr pScrn) if (!pScrn->vtSema) return 1000; - for (i = 0; i < pI830->xf86_config.num_output; i++) { + for (i = 0; i < xf86_config->num_output; i++) { enum output_status ret; char *result; diff --git a/src/i830_lvds.c b/src/i830_lvds.c index 4027a256..43070259 100644 --- a/src/i830_lvds.c +++ b/src/i830_lvds.c @@ -135,12 +135,13 @@ i830_lvds_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode) { ScrnInfoPtr pScrn = output->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); I830CrtcPrivatePtr intel_crtc = output->crtc->driver_private; int i; - for (i = 0; i < pI830->xf86_config.num_output; i++) { - xf86OutputPtr other_output = pI830->xf86_config.output[i]; + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr other_output = xf86_config->output[i]; if (other_output != output && other_output->crtc == output->crtc) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, diff --git a/src/i830_randr.c b/src/i830_randr.c index 2d986df2..290cb10d 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -495,13 +495,17 @@ xf86RandR12CrtcNotify (RRCrtcPtr randr_crtc) int y; Rotation rotation; int numOutputs; - RROutputPtr randr_outputs[XF86_MAX_OUTPUT]; + RROutputPtr *randr_outputs; RROutputPtr randr_output; xf86CrtcPtr crtc = randr_crtc->devPrivate; xf86OutputPtr output; int i, j; DisplayModePtr curMode = &crtc->curMode; + Bool ret; + randr_outputs = ALLOCATE_LOCAL(config->num_output * sizeof (RROutputPtr)); + if (!randr_outputs) + return FALSE; x = crtc->x; y = crtc->y; rotation = RR_Rotate_0; @@ -529,8 +533,10 @@ xf86RandR12CrtcNotify (RRCrtcPtr randr_crtc) } } } - return RRCrtcNotify (randr_crtc, randr_mode, x, y, - rotation, numOutputs, randr_outputs); + ret = RRCrtcNotify (randr_crtc, randr_mode, x, y, + rotation, numOutputs, randr_outputs); + DEALLOCATE_LOCAL(randr_outputs); + return ret; } static Bool @@ -550,9 +556,10 @@ xf86RandR12CrtcSet (ScreenPtr pScreen, Bool changed = FALSE; Bool pos_changed; int o, ro; - xf86CrtcPtr save_crtcs[XF86_MAX_OUTPUT]; + xf86CrtcPtr *save_crtcs; Bool save_enabled = crtc->enabled; + save_crtcs = ALLOCATE_LOCAL(config->num_crtc * sizeof (xf86CrtcPtr)); if ((mode != NULL) != crtc->enabled) changed = TRUE; else if (mode && !xf86ModesEqual (&crtc->curMode, mode)) @@ -606,6 +613,7 @@ xf86RandR12CrtcSet (ScreenPtr pScreen, xf86OutputPtr output = config->output[o]; output->crtc = save_crtcs[o]; } + DEALLOCATE_LOCAL(save_crtcs); return FALSE; } crtc->desiredMode = *mode; @@ -616,6 +624,7 @@ xf86RandR12CrtcSet (ScreenPtr pScreen, } if (pos_changed && mode) i830PipeSetBase(crtc, x, y); + DEALLOCATE_LOCAL(save_crtcs); return xf86RandR12CrtcNotify (randr_crtc); } @@ -694,13 +703,15 @@ xf86RandR12SetInfo12 (ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - RROutputPtr clones[XF86_MAX_OUTPUT]; - RRCrtcPtr crtcs[XF86_MAX_CRTC]; + RROutputPtr *clones; + RRCrtcPtr *crtcs; int ncrtc; int o, c, l; RRCrtcPtr randr_crtc; int nclone; + clones = ALLOCATE_LOCAL(config->num_output * sizeof (RROutputPtr)); + crtcs = ALLOCATE_LOCAL (config->num_crtc * sizeof (RRCrtcPtr)); for (o = 0; o < config->num_output; o++) { xf86OutputPtr output = config->output[o]; @@ -716,7 +727,11 @@ xf86RandR12SetInfo12 (ScreenPtr pScreen) randr_crtc = NULL; if (!RROutputSetCrtcs (output->randr_output, crtcs, ncrtc)) + { + DEALLOCATE_LOCAL (crtcs); + DEALLOCATE_LOCAL (clones); return FALSE; + } RROutputSetCrtc (output->randr_output, randr_crtc); RROutputSetPhysicalSize(output->randr_output, @@ -750,8 +765,14 @@ xf86RandR12SetInfo12 (ScreenPtr pScreen) clones[nclone++] = clone->randr_output; } if (!RROutputSetClones (output->randr_output, clones, nclone)) + { + DEALLOCATE_LOCAL (crtcs); + DEALLOCATE_LOCAL (clones); return FALSE; + } } + DEALLOCATE_LOCAL (crtcs); + DEALLOCATE_LOCAL (clones); return TRUE; } diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index 90a62c00..fc17efde 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -951,12 +951,12 @@ i830_sdvo_dump_device(xf86OutputPtr output) void i830_sdvo_dump(ScrnInfoPtr pScrn) { - I830Ptr pI830 = I830PTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); int i; - for (i = 0; i < pI830->xf86_config.num_output; i++) + for (i = 0; i < xf86_config->num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; + xf86OutputPtr output = xf86_config->output[i]; I830OutputPrivatePtr intel_output = output->driver_private; if (intel_output->type == I830_OUTPUT_SDVO) @@ -995,7 +995,7 @@ static DisplayModePtr i830_sdvo_get_modes(xf86OutputPtr output) { ScrnInfoPtr pScrn = output->scrn; - I830Ptr pI830 = I830PTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); DisplayModePtr modes; xf86OutputPtr crt; @@ -1008,7 +1008,7 @@ i830_sdvo_get_modes(xf86OutputPtr output) * but it does load-detect as connected. So, just steal the DDC bits from * analog when we fail at finding it the right way. */ - crt = pI830->xf86_config.output[0]; + crt = xf86_config->output[0]; if (crt->funcs->detect(crt) == XF86OutputStatusDisconnected) { return crt->funcs->get_modes(crt); } diff --git a/src/i830_tv.c b/src/i830_tv.c index 42c2aadd..ccb6aac2 100644 --- a/src/i830_tv.c +++ b/src/i830_tv.c @@ -356,11 +356,11 @@ i830_tv_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode) { ScrnInfoPtr pScrn = output->scrn; - I830Ptr pI830 = I830PTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); int i; - for (i = 0; i < pI830->xf86_config.num_output; i++) { - xf86OutputPtr other_output = pI830->xf86_config.output[i]; + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr other_output = xf86_config->output[i]; if (other_output != output && other_output->crtc == output->crtc) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, diff --git a/src/i830_video.c b/src/i830_video.c index 59794156..d10fd168 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -3514,6 +3514,7 @@ void i830_crtc_dpms_video(xf86CrtcPtr crtc, Bool on) { ScrnInfoPtr pScrn = crtc->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); I830PortPrivPtr pPriv; I830CrtcPrivatePtr intel_crtc = crtc->driver_private; @@ -3551,7 +3552,7 @@ i830_crtc_dpms_video(xf86CrtcPtr crtc, Bool on) } /* Check we have an LFP connected */ - if (i830PipeHasType(pI830->xf86_config.crtc[pPriv->pipe], + if (i830PipeHasType(xf86_config->crtc[pPriv->pipe], I830_OUTPUT_LVDS)) { size = pPriv->pipe ? INREG(PIPEBSRC) : INREG(PIPEASRC); hsize = (size >> 16) & 0x7FF; diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c index 25657e65..6b73264d 100644 --- a/src/i830_xf86Crtc.c +++ b/src/i830_xf86Crtc.c @@ -36,6 +36,36 @@ #include "i830_xf86Crtc.h" #include "X11/extensions/render.h" +/* + * Initialize xf86CrtcConfig structure + */ + +int xf86CrtcConfigPrivateIndex = -1; + +void +xf86CrtcConfigInit (ScrnInfoPtr scrn) +{ + xf86CrtcConfigPtr config; + + if (xf86CrtcConfigPrivateIndex == -1) + xf86CrtcConfigPrivateIndex = xf86AllocateScrnInfoPrivateIndex(); + config = xnfcalloc (1, sizeof (xf86CrtcConfigRec)); + scrn->privates[xf86CrtcConfigPrivateIndex].ptr = config; +} + +void +xf86CrtcSetSizeRange (ScrnInfoPtr scrn, + int minWidth, int minHeight, + int maxWidth, int maxHeight) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + + config->minWidth = minWidth; + config->minHeight = minHeight; + config->maxWidth = maxWidth; + config->maxHeight = maxHeight; +} + /* * Crtc functions */ @@ -44,7 +74,7 @@ xf86CrtcCreate (ScrnInfoPtr scrn, const xf86CrtcFuncsRec *funcs) { xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - xf86CrtcPtr crtc; + xf86CrtcPtr crtc, *crtcs; crtc = xcalloc (sizeof (xf86CrtcRec), 1); if (!crtc) @@ -54,6 +84,17 @@ xf86CrtcCreate (ScrnInfoPtr scrn, #ifdef RANDR_12_INTERFACE crtc->randr_crtc = NULL; #endif + if (xf86_config->crtc) + crtcs = xrealloc (xf86_config->crtc, + (xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr)); + else + crtcs = xalloc ((xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr)); + if (!crtcs) + { + xfree (crtc); + return NULL; + } + xf86_config->crtc = crtcs; xf86_config->crtc[xf86_config->num_crtc++] = crtc; return crtc; } @@ -85,7 +126,7 @@ xf86OutputCreate (ScrnInfoPtr scrn, const xf86OutputFuncsRec *funcs, const char *name) { - xf86OutputPtr output; + xf86OutputPtr output, *outputs; xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); int len = strlen (name); @@ -100,6 +141,17 @@ xf86OutputCreate (ScrnInfoPtr scrn, #ifdef RANDR_12_INTERFACE output->randr_output = NULL; #endif + if (xf86_config->output) + outputs = xrealloc (xf86_config->output, + (xf86_config->num_output + 1) * sizeof (xf86OutputPtr)); + else + outputs = xalloc ((xf86_config->num_output + 1) * sizeof (xf86OutputPtr)); + if (!outputs) + { + xfree (output); + return NULL; + } + xf86_config->output = outputs; xf86_config->output[xf86_config->num_output++] = output; return output; } diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h index f2c2429f..9294ccc2 100644 --- a/src/i830_xf86Crtc.h +++ b/src/i830_xf86Crtc.h @@ -307,26 +307,39 @@ struct _xf86Output { #endif }; -/* XXX yes, static allocation is a kludge */ -#define XF86_MAX_CRTC 4 -#define XF86_MAX_OUTPUT 16 - typedef struct _xf86CrtcConfig { - int num_output; - xf86OutputPtr output[XF86_MAX_OUTPUT]; - /** - * compat_output is used whenever we deal - * with legacy code that only understands a single - * output. pScrn->modes will be loaded from this output, - * adjust frame will whack this output, etc. - */ - int compat_output; - - int num_crtc; - xf86CrtcPtr crtc[XF86_MAX_CRTC]; + int num_output; + xf86OutputPtr *output; + /** + * compat_output is used whenever we deal + * with legacy code that only understands a single + * output. pScrn->modes will be loaded from this output, + * adjust frame will whack this output, etc. + */ + int compat_output; + + int num_crtc; + xf86CrtcPtr *crtc; + + int minWidth, minHeight; + int maxWidth, maxHeight; } xf86CrtcConfigRec, *xf86CrtcConfigPtr; -#define XF86_CRTC_CONFIG_PTR(p) ((xf86CrtcConfigPtr) ((p)->driverPrivate)) +extern int xf86CrtcConfigPrivateIndex; + +#define XF86_CRTC_CONFIG_PTR(p) ((xf86CrtcConfigPtr) ((p)->privates[xf86CrtcConfigPrivateIndex].ptr)) + +/* + * Initialize xf86CrtcConfig structure + */ + +void +xf86CrtcConfigInit (ScrnInfoPtr scrn); + +void +xf86CrtcSetSizeRange (ScrnInfoPtr scrn, + int minWidth, int minHeight, + int maxWidth, int maxHeight); /* * Crtc functions From 2b5a5542ad7d1c558d1684a0a69b66bab6e9d001 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 14 Dec 2006 13:43:50 -0800 Subject: [PATCH 23/32] Change TV modes from Preferred to Driver. This avoids having the artificial TV mode size drive overall screen size. --- src/i830_tv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i830_tv.c b/src/i830_tv.c index ccb6aac2..af9826b0 100644 --- a/src/i830_tv.c +++ b/src/i830_tv.c @@ -702,7 +702,7 @@ i830_tv_get_modes(xf86OutputPtr output) new->VSyncEnd = 777; new->VTotal = 806; - new->type = M_T_PREFERRED; + new->type = M_T_DRIVER; return new; } From d4142abc68888178a8f6c54fdcece91e898bc9f5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 14 Dec 2006 13:49:08 -0800 Subject: [PATCH 24/32] Set frame buffer size ranges in xf86_config. Initialization and default configuration code needs to know the range of legitimate sizes for the frame buffer. --- src/i830_driver.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index d4f2aa37..a210b630 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -912,6 +912,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) Bool enable; const char *chipname; int num_pipe; + int max_width; #ifdef XF86DRI unsigned long savedMMSize; #endif @@ -970,10 +971,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) } else pI830->entityPrivate = NULL; - /* Allocate an xf86CrtcConfig */ - xf86CrtcConfigInit (pScrn); - xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - if (xf86RegisterResources(pI830->pEnt->index, 0, ResNone)) { PreInitCleanup(pScrn); return FALSE; @@ -1181,6 +1178,16 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) xf86DrvMsg(pScrn->scrnIndex, from, "IO registers at addr 0x%lX\n", (unsigned long)pI830->MMIOAddr); + /* Allocate an xf86CrtcConfig */ + xf86CrtcConfigInit (pScrn); + xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + + if (IS_I965G(pI830)) + max_width = 16384; + else + max_width = 8192 / pI830->cpp; + xf86CrtcSetSizeRange (pScrn, 320, 200, max_width, 2048); + /* Some of the probing needs MMIO access, so map it here. */ I830MapMMIO(pScrn); @@ -1836,6 +1843,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) if (pScrn->displayWidth * pI830->cpp > 8192) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot support frame buffer stride > 8K > DRI.\n"); pI830->disableTiling = TRUE; + pI830->directRenderingDisabled = TRUE; } if (pScrn->virtualY > 2048) { From 55e7a32096a58f7bb2380b04df6b3dd9dc8e5b6a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 14 Dec 2006 16:50:26 -0800 Subject: [PATCH 25/32] 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). --- src/i830_xf86Crtc.c | 78 ++++++++++++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 30 deletions(-) diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c index 6b73264d..76d6d039 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, DisplayModePtr match) 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, DisplayModePtr match) } 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 pScrn, int *widthp, int *heightp) 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 pScrn, int *widthp, int *heightp) { 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 pScrn) 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 pScrn) 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 pScrn) 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 pScrn) 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; From 082519f34b468d0c5aa08db74ff2b51cf411d743 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 14 Dec 2006 16:51:48 -0800 Subject: [PATCH 26/32] 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. --- src/i830_display.c | 91 +++++++++++++++++++++++++++++++--------------- src/i830_driver.c | 14 ++++++- src/i830_lvds.c | 2 + src/i830_sdvo.c | 13 +++++-- 4 files changed, 85 insertions(+), 35 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index 4a429fc1..897a4ee5 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -506,22 +506,25 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mode) 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 mode) /* 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 mode) /* 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, DisplayModePtr mode, 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, DisplayModePtr mode, 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, DisplayModePtr mode, * 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, DisplayModePtr mode, */ 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 a210b630..97f52853 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 43070259..b682b27f 100644 --- a/src/i830_lvds.c +++ b/src/i830_lvds.c @@ -196,11 +196,13 @@ i830_lvds_mode_set(xf86OutputPtr output, DisplayModePtr mode, 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 fc17efde..d19b8b04 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -679,26 +679,31 @@ i830_sdvo_dpms(xf86OutputPtr output, int mode) 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); From 60411bc4d0b3c53850c73b7246d5f7ed5c2d4084 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 14 Dec 2006 18:36:44 -0800 Subject: [PATCH 27/32] Follow BIOS PLL write protocol (disable,enable,enable). This gets VGA output and text restore working, but SDVO is still not working. --- src/i830_display.c | 18 ++++++++++++--- src/i830_driver.c | 57 ++++++++++++++++++++++++---------------------- 2 files changed, 45 insertions(+), 30 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index 897a4ee5..f7f250dc 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -507,10 +507,17 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mode) /* Enable the DPLL */ temp = INREG(dpll_reg); if ((temp & DPLL_VCO_ENABLE) == 0) + { + OUTREG(dpll_reg, temp); + /* Wait for the clocks to stabilize. */ + usleep(150); OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE); - - /* Wait for the clocks to stabilize. */ - usleep(150); + /* Wait for the clocks to stabilize. */ + usleep(150); + OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE); + /* Wait for the clocks to stabilize. */ + usleep(150); + } /* Enable the pipe */ temp = INREG(pipeconf_reg); @@ -794,6 +801,11 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, OUTREG(dpll_reg, dpll); /* Wait for the clocks to stabilize. */ usleep(150); + + /* write it again -- the BIOS does, after all */ + 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 diff --git a/src/i830_driver.c b/src/i830_driver.c index 97f52853..373bc219 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -2233,19 +2233,8 @@ RestoreHWState(ScrnInfoPtr pScrn) usleep(150); } OUTREG(DPLL_A, pI830->saveDPLL_A); - if(xf86_config->num_crtc == 2) { - OUTREG(FPB0, pI830->saveFPB0); - OUTREG(FPB1, pI830->saveFPB1); - 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); + OUTREG(DPLL_A, pI830->saveDPLL_A); usleep(150); OUTREG(HTOTAL_A, pI830->saveHTOTAL_A); @@ -2257,13 +2246,32 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(DSPASTRIDE, pI830->saveDSPASTRIDE); OUTREG(DSPASIZE, pI830->saveDSPASIZE); OUTREG(DSPAPOS, pI830->saveDSPAPOS); - OUTREG(DSPABASE, pI830->saveDSPABASE); + OUTREG(PIPEACONF, pI830->savePIPEACONF); OUTREG(PIPEASRC, pI830->savePIPEASRC); + OUTREG(DSPACNTR, pI830->saveDSPACNTR); + OUTREG(DSPABASE, pI830->saveDSPABASE); + if (IS_I965G(pI830)) { + OUTREG(DSPASURF, pI830->saveDSPASURF); + } for(i = 0; i < 256; i++) { OUTREG(PALETTE_A + (i << 2), pI830->savePaletteA[i]); } if(xf86_config->num_crtc == 2) { + OUTREG(FPB0, pI830->saveFPB0); + OUTREG(FPB1, pI830->saveFPB1); + if (IS_I965G(pI830)) + OUTREG(DPLL_B_MD, pI830->saveDPLL_B_MD); + if (pI830->saveDPLL_B & DPLL_VCO_ENABLE) + { + OUTREG(DPLL_B, pI830->saveDPLL_B & ~DPLL_VCO_ENABLE); + usleep(150); + } + OUTREG(DPLL_B, pI830->saveDPLL_B); + usleep(150); + OUTREG(DPLL_B, pI830->saveDPLL_B); + usleep(150); + OUTREG(HTOTAL_B, pI830->saveHTOTAL_B); OUTREG(HBLANK_B, pI830->saveHBLANK_B); OUTREG(HSYNC_B, pI830->saveHSYNC_B); @@ -2273,8 +2281,13 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(DSPBSTRIDE, pI830->saveDSPBSTRIDE); OUTREG(DSPBSIZE, pI830->saveDSPBSIZE); OUTREG(DSPBPOS, pI830->saveDSPBPOS); - OUTREG(DSPBBASE, pI830->saveDSPBBASE); OUTREG(PIPEBSRC, pI830->savePIPEBSRC); + OUTREG(PIPEBCONF, pI830->savePIPEBCONF); + OUTREG(DSPBCNTR, pI830->saveDSPBCNTR); + OUTREG(DSPBBASE, pI830->saveDSPBBASE); + if (IS_I965G(pI830)) { + OUTREG(DSPBSURF, pI830->saveDSPBSURF); + } for(i= 0; i < 256; i++) { OUTREG(PALETTE_B + (i << 2), pI830->savePaletteB[i]); } @@ -2283,27 +2296,17 @@ RestoreHWState(ScrnInfoPtr pScrn) if (!IS_I830(pI830) && !IS_845G(pI830)) OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL); - if (IS_I965G(pI830)) { - OUTREG(DSPASURF, pI830->saveDSPASURF); - OUTREG(DSPBSURF, pI830->saveDSPBSURF); - } - OUTREG(VCLK_DIVISOR_VGA0, pI830->saveVCLK_DIVISOR_VGA0); OUTREG(VCLK_DIVISOR_VGA1, pI830->saveVCLK_DIVISOR_VGA1); OUTREG(VCLK_POST_DIV, pI830->saveVCLK_POST_DIV); - OUTREG(PIPEACONF, pI830->savePIPEACONF); - OUTREG(PIPEBCONF, pI830->savePIPEBCONF); - - OUTREG(VGACNTRL, pI830->saveVGACNTRL); - OUTREG(DSPACNTR, pI830->saveDSPACNTR); - OUTREG(DSPBCNTR, pI830->saveDSPBCNTR); - for (i = 0; i < xf86_config->num_output; i++) { xf86OutputPtr output = xf86_config->output[i]; (*output->funcs->restore) (output); } + OUTREG(VGACNTRL, pI830->saveVGACNTRL); + for(i = 0; i < 7; i++) { OUTREG(SWF0 + (i << 2), pI830->saveSWF[i]); OUTREG(SWF00 + (i << 2), pI830->saveSWF[i+7]); From 9b1a1b170befae2e705c23ce295837d0d13b60c0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 16 Dec 2006 16:53:49 -0800 Subject: [PATCH 28/32] reorder restore writes for 965 VGA --- src/i830_display.c | 2 ++ src/i830_driver.c | 22 +++++++++++++--------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index f7f250dc..6971e28a 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -765,9 +765,11 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, else pipeconf &= ~PIPEACONF_DOUBLE_WIDE; } +#if 1 dspcntr |= DISPLAY_PLANE_ENABLE; pipeconf |= PIPEACONF_ENABLE; dpll |= DPLL_VCO_ENABLE; +#endif if (is_lvds) { diff --git a/src/i830_driver.c b/src/i830_driver.c index 373bc219..998b36f2 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -2223,18 +2223,19 @@ RestoreHWState(ScrnInfoPtr pScrn) crtc->funcs->dpms(crtc, DPMSModeOff); } - OUTREG(FPA0, pI830->saveFPA0); - OUTREG(FPA1, pI830->saveFPA1); - 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(FPA0, pI830->saveFPA0); + OUTREG(FPA1, pI830->saveFPA1); OUTREG(DPLL_A, pI830->saveDPLL_A); usleep(150); - OUTREG(DPLL_A, pI830->saveDPLL_A); + if (IS_I965G(pI830)) + OUTREG(DPLL_A_MD, pI830->saveDPLL_A_MD); + else + OUTREG(DPLL_A, pI830->saveDPLL_A); usleep(150); OUTREG(HTOTAL_A, pI830->saveHTOTAL_A); @@ -2243,16 +2244,19 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(VTOTAL_A, pI830->saveVTOTAL_A); OUTREG(VBLANK_A, pI830->saveVBLANK_A); OUTREG(VSYNC_A, pI830->saveVSYNC_A); + OUTREG(DSPASTRIDE, pI830->saveDSPASTRIDE); OUTREG(DSPASIZE, pI830->saveDSPASIZE); OUTREG(DSPAPOS, pI830->saveDSPAPOS); - OUTREG(PIPEACONF, pI830->savePIPEACONF); - OUTREG(PIPEASRC, pI830->savePIPEASRC); OUTREG(DSPACNTR, pI830->saveDSPACNTR); OUTREG(DSPABASE, pI830->saveDSPABASE); if (IS_I965G(pI830)) { OUTREG(DSPASURF, pI830->saveDSPASURF); } + + OUTREG(PIPEASRC, pI830->savePIPEASRC); + OUTREG(PIPEACONF, pI830->savePIPEACONF); + for(i = 0; i < 256; i++) { OUTREG(PALETTE_A + (i << 2), pI830->savePaletteA[i]); } @@ -2296,6 +2300,8 @@ RestoreHWState(ScrnInfoPtr pScrn) if (!IS_I830(pI830) && !IS_845G(pI830)) OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL); + OUTREG(VGACNTRL, pI830->saveVGACNTRL); + OUTREG(VCLK_DIVISOR_VGA0, pI830->saveVCLK_DIVISOR_VGA0); OUTREG(VCLK_DIVISOR_VGA1, pI830->saveVCLK_DIVISOR_VGA1); OUTREG(VCLK_POST_DIV, pI830->saveVCLK_POST_DIV); @@ -2305,8 +2311,6 @@ RestoreHWState(ScrnInfoPtr pScrn) (*output->funcs->restore) (output); } - OUTREG(VGACNTRL, pI830->saveVGACNTRL); - for(i = 0; i < 7; i++) { OUTREG(SWF0 + (i << 2), pI830->saveSWF[i]); OUTREG(SWF00 + (i << 2), pI830->saveSWF[i+7]); From bffd611b0a1cb05868e0f93e6ff9357a3116eaa6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 16 Dec 2006 21:03:15 -0800 Subject: [PATCH 29/32] Follow BIOS order in writing DPLL/DPLL_MD registers. 965 BIOS writes DPLL and then DPLL_MD. 945 BIOS writes DPLL twice. --- src/i830_display.c | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index 6971e28a..f87aadca 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -787,12 +787,6 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, 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); @@ -804,21 +798,17 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, /* Wait for the clocks to stabilize. */ usleep(150); - /* write it again -- the BIOS does, after all */ - 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)); + } else { + /* write it again -- the BIOS does, after all */ + 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 - * INREG for presumable pci write posting magic before and after the dpll - * write above. - */ - OUTREG(dpll_reg, dpll); -#endif - OUTREG(htot_reg, (adjusted_mode->CrtcHDisplay - 1) | ((adjusted_mode->CrtcHTotal - 1) << 16)); OUTREG(hblank_reg, (adjusted_mode->CrtcHBlankStart - 1) | From 8e6ab99b3195325f9fe5432725fe328591c0c7e2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 16 Dec 2006 21:06:36 -0800 Subject: [PATCH 30/32] Not restoring active outputs. Wait for input sync before enabling outputs. Oops--looks like a typo to me; the code was callint set_target_output instead of set_active_outputs. BIOS loops waiting for the SDVO input to sync before enabling outputs, this makes sense to me. --- src/i830_sdvo.c | 57 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 20 deletions(-) diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index d19b8b04..cb68802a 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -693,18 +693,16 @@ i830_sdvo_dpms(xf86OutputPtr output, int mode) 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); + /* 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); @@ -716,6 +714,8 @@ i830_sdvo_dpms(xf86OutputPtr output, int mode) "First %s output reported failure to sync\n", SDVO_NAME(dev_priv)); } + + i830_sdvo_set_active_outputs(output, dev_priv->active_outputs); } } @@ -764,6 +764,21 @@ i830_sdvo_restore(xf86OutputPtr output) struct i830_sdvo_priv *dev_priv = intel_output->dev_priv; I830Ptr pI830 = I830PTR(pScrn); int o; + int i; + Bool input1, input2; + CARD8 status; + + i830_sdvo_set_active_outputs(output, 0); + + for (o = SDVO_OUTPUT_FIRST; o <= SDVO_OUTPUT_LAST; o++) + { + CARD16 this_output = (1 << o); + if (dev_priv->caps.output_flags & this_output) + { + i830_sdvo_set_target_output(output, this_output); + i830_sdvo_set_output_timing(output, &dev_priv->save_output_dtd[o]); + } + } if (dev_priv->caps.sdvo_inputs_mask & 0x1) { i830_sdvo_set_target_input(output, TRUE, FALSE); @@ -775,20 +790,22 @@ i830_sdvo_restore(xf86OutputPtr output) i830_sdvo_set_input_timing(output, &dev_priv->save_input_dtd_2); } - for (o = SDVO_OUTPUT_FIRST; o <= SDVO_OUTPUT_LAST; o++) - { - CARD16 this_output = (1 << o); - if (dev_priv->caps.output_flags & this_output) - { - i830_sdvo_set_target_output(output, this_output); - i830_sdvo_set_output_timing(output, &dev_priv->save_output_dtd[o]); - } - } - i830_sdvo_set_target_output(output, dev_priv->save_active_outputs); - i830_sdvo_set_clock_rate_mult(output, dev_priv->save_sdvo_mult); OUTREG(dev_priv->output_device, dev_priv->save_SDVOX); + + if (dev_priv->save_SDVOX & SDVO_ENABLE) + { + for (i = 0; i < 2; i++) + i830WaitForVblank(pScrn); + status = i830_sdvo_get_trained_inputs(output, &input1, &input2); + if (status == SDVO_CMD_STATUS_SUCCESS && !input1) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "First %s output reported failure to sync\n", + SDVO_NAME(dev_priv)); + } + + i830_sdvo_set_active_outputs(output, dev_priv->save_active_outputs); } static int From 86558cc622b516b568cc26efdf9b64d4b660f50f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 16 Dec 2006 21:09:31 -0800 Subject: [PATCH 31/32] Prefer earliest CRTC when mapping to outputs. For some reason, the code was preferring the last possible output when mapping outputs to crtcs. Use the earlier CRTC instead to make the i830 driver consistent with BIOS usage. --- src/i830_xf86Crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c index 76d6d039..51e6f1c7 100644 --- a/src/i830_xf86Crtc.c +++ b/src/i830_xf86Crtc.c @@ -359,7 +359,7 @@ xf86PickCrtcs (ScrnInfoPtr pScrn, crtcs[n] = crtc; memcpy (crtcs, best_crtcs, n * sizeof (xf86CrtcPtr)); score = my_score + xf86PickCrtcs (pScrn, crtcs, modes, n+1, width, height); - if (score >= best_score) + if (score > best_score) { best_crtc = crtc; best_score = score; From 6823ca87f3b1ef3b28ed167254dcfce2a80467df Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 16 Dec 2006 21:12:47 -0800 Subject: [PATCH 32/32] Follow mode setting order in RestoreHWState. Add delays after output and CRTC disable. Restore panel fit register before PLLs are restarted. Move all VGA restore code last. Shuffle various register writes around and add delays to match PipeSetMode code. --- src/i830_driver.c | 80 ++++++++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 36 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index 998b36f2..7da4bf55 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -2210,18 +2210,22 @@ RestoreHWState(ScrnInfoPtr pScrn) #ifdef XF86DRI I830DRISetVBlankInterrupt (pScrn, FALSE); #endif - /* 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]; crtc->funcs->dpms(crtc, DPMSModeOff); } + i830WaitForVblank(pScrn); + + if (!IS_I830(pI830) && !IS_845G(pI830)) + OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL); if (pI830->saveDPLL_A & DPLL_VCO_ENABLE) { @@ -2248,32 +2252,31 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(DSPASTRIDE, pI830->saveDSPASTRIDE); OUTREG(DSPASIZE, pI830->saveDSPASIZE); OUTREG(DSPAPOS, pI830->saveDSPAPOS); - OUTREG(DSPACNTR, pI830->saveDSPACNTR); - OUTREG(DSPABASE, pI830->saveDSPABASE); - if (IS_I965G(pI830)) { - OUTREG(DSPASURF, pI830->saveDSPASURF); - } - OUTREG(PIPEASRC, pI830->savePIPEASRC); + OUTREG(DSPABASE, pI830->saveDSPABASE); + if (IS_I965G(pI830)) + OUTREG(DSPASURF, pI830->saveDSPASURF); OUTREG(PIPEACONF, pI830->savePIPEACONF); + i830WaitForVblank(pScrn); + OUTREG(DSPACNTR, pI830->saveDSPACNTR); + OUTREG(DSPABASE, INREG(DSPABASE)); + i830WaitForVblank(pScrn); - for(i = 0; i < 256; i++) { - OUTREG(PALETTE_A + (i << 2), pI830->savePaletteA[i]); - } - - if(xf86_config->num_crtc == 2) { - OUTREG(FPB0, pI830->saveFPB0); - OUTREG(FPB1, pI830->saveFPB1); - if (IS_I965G(pI830)) - OUTREG(DPLL_B_MD, pI830->saveDPLL_B_MD); + if(xf86_config->num_crtc == 2) + { if (pI830->saveDPLL_B & DPLL_VCO_ENABLE) { OUTREG(DPLL_B, pI830->saveDPLL_B & ~DPLL_VCO_ENABLE); usleep(150); } + OUTREG(FPB0, pI830->saveFPB0); + OUTREG(FPB1, pI830->saveFPB1); OUTREG(DPLL_B, pI830->saveDPLL_B); usleep(150); - OUTREG(DPLL_B, pI830->saveDPLL_B); + if (IS_I965G(pI830)) + OUTREG(DPLL_B_MD, pI830->saveDPLL_B_MD); + else + OUTREG(DPLL_B, pI830->saveDPLL_B); usleep(150); OUTREG(HTOTAL_B, pI830->saveHTOTAL_B); @@ -2286,43 +2289,48 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(DSPBSIZE, pI830->saveDSPBSIZE); OUTREG(DSPBPOS, pI830->saveDSPBPOS); OUTREG(PIPEBSRC, pI830->savePIPEBSRC); - OUTREG(PIPEBCONF, pI830->savePIPEBCONF); - OUTREG(DSPBCNTR, pI830->saveDSPBCNTR); OUTREG(DSPBBASE, pI830->saveDSPBBASE); - if (IS_I965G(pI830)) { + if (IS_I965G(pI830)) OUTREG(DSPBSURF, pI830->saveDSPBSURF); - } - for(i= 0; i < 256; i++) { - OUTREG(PALETTE_B + (i << 2), pI830->savePaletteB[i]); - } + OUTREG(PIPEBCONF, pI830->savePIPEBCONF); + i830WaitForVblank(pScrn); + OUTREG(DSPBCNTR, pI830->saveDSPBCNTR); + OUTREG(DSPBBASE, INREG(DSPBBASE)); + i830WaitForVblank(pScrn); } - if (!IS_I830(pI830) && !IS_845G(pI830)) - OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL); - + /* Restore outputs */ + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + if (output->funcs->restore) + output->funcs->restore(output); + } + OUTREG(VGACNTRL, pI830->saveVGACNTRL); OUTREG(VCLK_DIVISOR_VGA0, pI830->saveVCLK_DIVISOR_VGA0); OUTREG(VCLK_DIVISOR_VGA1, pI830->saveVCLK_DIVISOR_VGA1); OUTREG(VCLK_POST_DIV, pI830->saveVCLK_POST_DIV); - for (i = 0; i < xf86_config->num_output; i++) { - xf86OutputPtr output = xf86_config->output[i]; - (*output->funcs->restore) (output); + for(i = 0; i < 256; i++) { + OUTREG(PALETTE_A + (i << 2), pI830->savePaletteA[i]); + } + + if(xf86_config->num_crtc == 2) { + for(i= 0; i < 256; i++) { + OUTREG(PALETTE_B + (i << 2), pI830->savePaletteB[i]); + } } for(i = 0; i < 7; i++) { - OUTREG(SWF0 + (i << 2), pI830->saveSWF[i]); - OUTREG(SWF00 + (i << 2), pI830->saveSWF[i+7]); + OUTREG(SWF0 + (i << 2), pI830->saveSWF[i]); + OUTREG(SWF00 + (i << 2), pI830->saveSWF[i+7]); } OUTREG(SWF30, pI830->saveSWF[14]); OUTREG(SWF31, pI830->saveSWF[15]); OUTREG(SWF32, pI830->saveSWF[16]); - for (i = 0; i < 2; i++) - i830WaitForVblank(pScrn); - vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS); vgaHWLock(hwp);