summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile.am5
-rw-r--r--src/i830.h1
-rw-r--r--src/i830_display.c5
-rw-r--r--src/i830_modes.c297
-rw-r--r--src/i830_sdvo.h3
-rw-r--r--src/i830_xf86Modes.c348
-rw-r--r--src/i830_xf86Modes.h40
7 files changed, 531 insertions, 168 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 8970db1e..f8aaad1d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -63,8 +63,9 @@ i810_drv_la_SOURCES = \
i830_video.c \
i830_rotate.c \
i830_randr.c \
- i830_sdvo.c
-
+ i830_sdvo.c \
+ i830_xf86Modes.h \
+ i830_xf86Modes.c
if DRI
i810_drv_la_SOURCES += \
i810_dri.c \
diff --git a/src/i830.h b/src/i830.h
index c4a4771e..b3a0895c 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -403,6 +403,7 @@ typedef struct _I830Rec {
int planeEnabled[MAX_DISPLAY_PIPES];
xf86MonPtr pipeMon[MAX_DISPLAY_PIPES];
DisplayModePtr pipeModes[MAX_DISPLAY_PIPES];
+ DisplayModeRec pipeCurMode[MAX_DISPLAY_PIPES];
/* Driver phase/state information */
Bool preinit;
diff --git a/src/i830_display.c b/src/i830_display.c
index 50f49402..1546c377 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -35,6 +35,7 @@
#include "i830_bios.h"
#include "i830_display.h"
#include "i830_debug.h"
+#include "i830_xf86Modes.h"
/** Returns the pixel clock for the given refclk and divisors. */
static int i830_clock(int refclk, int m1, int m2, int n, int p1, int p2)
@@ -299,6 +300,8 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe)
pMode = pBest;
}
}
+ if (I830ModesEqual(&pI830->pipeCurMode[pipe], pMode))
+ return TRUE;
ErrorF("Requested pix clock: %d\n", pMode->Clock);
@@ -629,6 +632,8 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe)
OUTREG(SDVOC, sdvoc);
}
+ pI830->pipeCurMode[pipe] = *pMode;
+
return TRUE;
}
diff --git a/src/i830_modes.c b/src/i830_modes.c
index faa843e3..e1e5fd53 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -42,9 +42,11 @@
#include <stdio.h>
#include <string.h>
+#include <assert.h>
#include "xf86.h"
#include "i830.h"
+#include "i830_xf86Modes.h"
#include <math.h>
@@ -92,6 +94,8 @@ static struct
{720, 400, 70},
};
+#define DEBUG_REPROBE 1
+
extern const int i830refreshes[];
void
@@ -157,6 +161,23 @@ I830PrintModes(ScrnInfoPtr scrp)
} while (p != NULL && p != scrp->modes);
}
+/**
+ * Allocates and returns a copy of pMode, including pointers within pMode.
+ */
+static DisplayModePtr
+I830DuplicateMode(DisplayModePtr pMode)
+{
+ DisplayModePtr pNew;
+
+ pNew = xnfalloc(sizeof(DisplayModeRec));
+ *pNew = *pMode;
+ pNew->next = NULL;
+ pNew->prev = NULL;
+ pNew->name = xnfstrdup(pMode->name);
+
+ return pNew;
+}
+
/* This function will sort all modes according to their resolution.
* Highest resolution first.
*/
@@ -200,32 +221,31 @@ I830xf86SortModes(DisplayModePtr *new, DisplayModePtr *first,
}
/**
- * Calculates the vertical refresh of a mode.
+ * Gets a new pointer to a VESA established mode.
*
- * Taken directly from xf86Mode.c, and should be put back there --Eric Anholt
+ * \param i index into the VESA established modes table.
*/
-static double
-I830ModeVRefresh(DisplayModePtr mode)
+static DisplayModePtr
+I830GetVESAEstablishedMode(ScrnInfoPtr pScrn, int i)
{
- double refresh = 0.0;
+ DisplayModePtr pMode;
- if (mode->VRefresh > 0.0)
- refresh = mode->VRefresh;
- else if (mode->HTotal > 0 && mode->VTotal > 0) {
- refresh = mode->Clock * 1000.0 / mode->HTotal / mode->VTotal;
- if (mode->Flags & V_INTERLACE)
- refresh *= 2.0;
- if (mode->Flags & V_DBLSCAN)
- refresh /= 2.0;
- if (mode->VScan > 1)
- refresh /= (float)(mode->VScan);
+ for (pMode = I830xf86DefaultModes; pMode->name != NULL; pMode = pMode->next)
+ {
+ if (pMode->HDisplay == est_timings[i].hsize &&
+ pMode->VDisplay == est_timings[i].vsize &&
+ fabs(I830ModeVRefresh(pMode) - est_timings[i].refresh) < 1.0)
+ {
+ DisplayModePtr pNew = I830DuplicateMode(pMode);
+ pNew->VRefresh = I830ModeVRefresh(pMode);
+ return pNew;
+ }
}
- return refresh;
+ return NULL;
}
DisplayModePtr I830GetDDCModes(ScrnInfoPtr pScrn, xf86MonPtr ddc)
{
- DisplayModePtr p;
DisplayModePtr last = NULL;
DisplayModePtr new = NULL;
DisplayModePtr first = NULL;
@@ -289,7 +309,16 @@ DisplayModePtr I830GetDDCModes(ScrnInfoPtr pScrn, xf86MonPtr ddc)
for (j = 0; j < 8; j++) {
if (ddc->timings2[j].hsize == 0 || ddc->timings2[j].vsize == 0)
continue;
+#if 1
+ new = i830GetGTF(ddc->timings2[j].hsize, ddc->timings2[j].vsize,
+ ddc->timings2[j].refresh, FALSE, FALSE);
+ new->status = MODE_OK;
+ new->type |= M_T_DEFAULT;
+
+ I830xf86SortModes(&new, &first, &last);
+#else
for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) {
+
/* Ignore all double scan modes */
if ((ddc->timings2[j].hsize == p->HDisplay) &&
(ddc->timings2[j].vsize == p->VDisplay)) {
@@ -318,39 +347,27 @@ DisplayModePtr I830GetDDCModes(ScrnInfoPtr pScrn, xf86MonPtr ddc)
}
}
}
+#endif
}
/* Search thru established modes from EDID */
tmp = (ddc->timings1.t1 << 8) | ddc->timings1.t2;
for (j = 0; j < 16; j++) {
if (tmp & (1 << j)) {
- for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) {
- if ((est_timings[j].hsize == p->HDisplay) &&
- (est_timings[j].vsize == p->VDisplay)) {
- float refresh =
- (float)p->Clock * 1000.0 / p->HTotal / p->VTotal;
- float err = (float)est_timings[j].refresh - refresh;
-
- if (err < 1.0) {
- /* Is this good enough? */
- new = xnfcalloc(1, sizeof (DisplayModeRec));
- memcpy(new, p, sizeof(DisplayModeRec));
- new->name = xnfalloc(strlen(p->name) + 1);
- strcpy(new->name, p->name);
- new->status = MODE_OK;
- new->type = M_T_DEFAULT;
-
- count++;
-
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "Valid Mode from established timing "
- "table: %s\n", new->name);
-
- I830xf86SortModes(&new, &first, &last);
- break;
- }
- }
- }
+ DisplayModePtr pNew;
+
+ pNew = I830GetVESAEstablishedMode(pScrn, j);
+ assert(pNew != NULL); /* We'd better have all the est. modes. */
+
+ new->status = MODE_OK;
+ new->type = M_T_DEFAULT;
+
+ count++;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Valid Mode from established "
+ "timing table: %s\n", new->name);
+
+ I830xf86SortModes(&new, &first, &last);
}
}
@@ -512,23 +529,6 @@ i830GetLVDSModes(ScrnInfoPtr pScrn, char **ppModeName)
}
/**
- * Allocates and returns a copy of pMode, including pointers within pMode.
- */
-static DisplayModePtr
-I830DuplicateMode(DisplayModePtr pMode)
-{
- DisplayModePtr pNew;
-
- pNew = xnfalloc(sizeof(DisplayModeRec));
- *pNew = *pMode;
- pNew->next = NULL;
- pNew->prev = NULL;
- pNew->name = xnfstrdup(pMode->name);
-
- return pNew;
-}
-
-/**
* Injects a list of probed modes into another mode list.
*
* Take the doubly-linked list of modes we've probed for the device, and injects
@@ -536,11 +536,11 @@ I830DuplicateMode(DisplayModePtr pMode)
* eventual call to xf86ValidateModes will do this for us. I think.
*/
int
-I830InjectProbedModes(ScrnInfoPtr pScrn, DisplayModePtr modeList,
- char **ppModeName, DisplayModePtr addModes)
+I830InjectProbedModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList,
+ DisplayModePtr addModes)
{
- DisplayModePtr last = modeList;
- DisplayModePtr first = modeList;
+ DisplayModePtr last = *modeList;
+ DisplayModePtr first = *modeList;
DisplayModePtr addMode;
int count = 0;
@@ -551,12 +551,14 @@ I830InjectProbedModes(ScrnInfoPtr pScrn, DisplayModePtr modeList,
*/
pNew = I830DuplicateMode(addMode);
+#if 0
/* If the user didn't specify any modes, mark all modes as M_T_USERDEF
* so that we can cycle through them, etc. XXX: really need to?
*/
- if (ppModeName[0] == NULL) {
+ if (pScrn->display->modes[0] == NULL) {
pNew->type |= M_T_USERDEF;
}
+#endif
/* Insert pNew into modeList */
if (last) {
@@ -571,6 +573,7 @@ I830InjectProbedModes(ScrnInfoPtr pScrn, DisplayModePtr modeList,
count++;
}
+ *modeList = first;
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Injected %d modes detected from the monitor\n", count);
@@ -578,97 +581,6 @@ I830InjectProbedModes(ScrnInfoPtr pScrn, DisplayModePtr modeList,
return count;
}
-/*
- * I830xf86SetModeCrtc
- *
- * Initialises the Crtc parameters for a mode. The initialisation includes
- * adjustments for interlaced and double scan modes.
- *
- * Taken directly from xf86Mode.c:xf86SetModeCrtc -- Eric Anholt
- * (and it should be put back there!)
- */
-static void
-I830xf86SetModeCrtc(DisplayModePtr p, int adjustFlags)
-{
- if ((p == NULL) || ((p->type & M_T_CRTC_C) == M_T_BUILTIN))
- return;
-
- p->CrtcHDisplay = p->HDisplay;
- p->CrtcHSyncStart = p->HSyncStart;
- p->CrtcHSyncEnd = p->HSyncEnd;
- p->CrtcHTotal = p->HTotal;
- p->CrtcHSkew = p->HSkew;
- p->CrtcVDisplay = p->VDisplay;
- p->CrtcVSyncStart = p->VSyncStart;
- p->CrtcVSyncEnd = p->VSyncEnd;
- p->CrtcVTotal = p->VTotal;
- if (p->Flags & V_INTERLACE) {
- if (adjustFlags & INTERLACE_HALVE_V) {
- p->CrtcVDisplay /= 2;
- p->CrtcVSyncStart /= 2;
- p->CrtcVSyncEnd /= 2;
- p->CrtcVTotal /= 2;
- }
- /* Force interlaced modes to have an odd VTotal */
- /* maybe we should only do this when INTERLACE_HALVE_V is set? */
- p->CrtcVTotal |= 1;
- }
-
- if (p->Flags & V_DBLSCAN) {
- p->CrtcVDisplay *= 2;
- p->CrtcVSyncStart *= 2;
- p->CrtcVSyncEnd *= 2;
- p->CrtcVTotal *= 2;
- }
- if (p->VScan > 1) {
- p->CrtcVDisplay *= p->VScan;
- p->CrtcVSyncStart *= p->VScan;
- p->CrtcVSyncEnd *= p->VScan;
- p->CrtcVTotal *= p->VScan;
- }
- p->CrtcHAdjusted = FALSE;
- p->CrtcVAdjusted = FALSE;
-
- /*
- * XXX
- *
- * The following is taken from VGA, but applies to other cores as well.
- */
- p->CrtcVBlankStart = min(p->CrtcVSyncStart, p->CrtcVDisplay);
- p->CrtcVBlankEnd = max(p->CrtcVSyncEnd, p->CrtcVTotal);
- if ((p->CrtcVBlankEnd - p->CrtcVBlankStart) >= 127) {
- /*
- * V Blanking size must be < 127.
- * Moving blank start forward is safer than moving blank end
- * back, since monitors clamp just AFTER the sync pulse (or in
- * the sync pulse), but never before.
- */
- p->CrtcVBlankStart = p->CrtcVBlankEnd - 127;
- /*
- * If VBlankStart is now > VSyncStart move VBlankStart
- * to VSyncStart using the maximum width that fits into
- * VTotal.
- */
- if (p->CrtcVBlankStart > p->CrtcVSyncStart) {
- p->CrtcVBlankStart = p->CrtcVSyncStart;
- p->CrtcVBlankEnd = min(p->CrtcHBlankStart + 127, p->CrtcVTotal);
- }
- }
- p->CrtcHBlankStart = min(p->CrtcHSyncStart, p->CrtcHDisplay);
- p->CrtcHBlankEnd = max(p->CrtcHSyncEnd, p->CrtcHTotal);
-
- if ((p->CrtcHBlankEnd - p->CrtcHBlankStart) >= 63 * 8) {
- /*
- * H Blanking size must be < 63*8. Same remark as above.
- */
- p->CrtcHBlankStart = p->CrtcHBlankEnd - 63 * 8;
- if (p->CrtcHBlankStart > p->CrtcHSyncStart) {
- p->CrtcHBlankStart = p->CrtcHSyncStart;
- p->CrtcHBlankEnd = min(p->CrtcHBlankStart + 63 * 8, p->CrtcHTotal);
- }
- }
-}
-
/**
* Performs probing of modes available on the output connected to the given
* pipe.
@@ -740,14 +652,21 @@ I830ReprobePipeModeList(ScrnInfoPtr pScrn, int pipe)
/* Set the vertical refresh, which is used by the choose-best-mode-per-pipe
* code later on.
*/
+#ifdef DEBUG_REPROBE
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Printing probed modes for pipe %d\n",
+ pipe);
+#endif
for (pMode = pI830->pipeModes[pipe]; pMode != NULL; pMode = pMode->next) {
pMode->VRefresh = I830ModeVRefresh(pMode);
+#ifdef DEBUG_REPROBE
+ PrintModeline(pScrn->scrnIndex, pMode);
+#endif
}
}
/**
* This function removes a mode from a list of modes. It should probably be
- * moved to xf86Mode.c
+ * moved to xf86Mode.c.
*
* There are different types of mode lists:
*
@@ -795,8 +714,9 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time)
I830Ptr pI830 = I830PTR(pScrn);
ClockRangePtr clockRanges;
int n, pipe;
- DisplayModePtr saved_mode;
+ DisplayModePtr saved_mode, availModes;
int saved_virtualX = 0, saved_virtualY = 0, saved_displayWidth = 0;
+ Bool pipes_reconfigured = FALSE;
for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) {
I830ReprobePipeModeList(pScrn, pipe);
@@ -815,6 +735,9 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time)
} else {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Enabled new CRT on pipe A\n");
+ pipes_reconfigured = TRUE;
+ /* Clear the current mode, so we reprogram the pipe for sure. */
+ memset(&pI830->pipeCurMode[0], 0, sizeof(pI830->pipeCurMode[0]));
}
} else if (((pI830->operatingDevices >> 8) & 0xff) == PIPE_NONE) {
pI830->operatingDevices |= PIPE_CRT << 8;
@@ -825,19 +748,24 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time)
} else {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Enabled new CRT on pipe B\n");
+ pipes_reconfigured = TRUE;
+ /* Clear the current mode, so we reprogram the pipe for sure. */
+ memset(&pI830->pipeCurMode[1], 0, sizeof(pI830->pipeCurMode[1]));
}
}
}
- /* XXX: Clean out modes previously injected by our driver */
-
+ /* Start by injecting the XFree86 default modes and user-configured
+ * modelines. XXX: This actually isn't of use if we've got any DDC, as DDC
+ * currently has higher priority than the validated modelist. We need to
+ * deal with that.
+ */
+ I830InjectProbedModes(pScrn, &availModes, pScrn->monitor->Modes);
if (pI830->pipeModes[0] != NULL) {
- I830InjectProbedModes(pScrn, pScrn->monitor->Modes,
- pScrn->display->modes, pI830->pipeModes[0]);
+ I830InjectProbedModes(pScrn, &availModes, pI830->pipeModes[0]);
}
if (pI830->pipeModes[1] != NULL) {
- I830InjectProbedModes(pScrn, pScrn->monitor->Modes,
- pScrn->display->modes, pI830->pipeModes[1]);
+ I830InjectProbedModes(pScrn, &availModes, pI830->pipeModes[1]);
}
/*
@@ -872,7 +800,7 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time)
* capabilities of our pipes.
*/
n = xf86ValidateModes(pScrn,
- pScrn->monitor->Modes, /* availModes */
+ availModes, /* availModes */
pScrn->display->modes, /* modeNames */
clockRanges, /* clockRanges */
!first_time ? &pScrn->displayWidth : NULL, /* linePitches */
@@ -886,6 +814,12 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time)
pI830->FbMapSize, /* apertureSize */
LOOKUP_BEST_REFRESH /* strategy */);
+ /* availModes is of no more use as xf86ValidateModes has duplicated and
+ * saved everything it needs.
+ */
+ while (availModes != NULL)
+ xf86DeleteMode(&availModes, availModes);
+
if (!first_time) {
/* Restore things that may have been damaged by xf86ValidateModes. */
pScrn->virtualX = saved_virtualX;
@@ -900,6 +834,19 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time)
xf86PruneDriverModes(pScrn);
+#if DEBUG_REPROBE
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Modes post revalidate\n");
+ do {
+ DisplayModePtr pMode;
+
+ for (pMode = pScrn->modes; ; pMode = pMode->next) {
+ PrintModeline(pScrn->scrnIndex, pMode);
+ if (pMode->next == pScrn->modes)
+ break;
+ }
+ } while (0);
+#endif
+
/* Try to find the closest equivalent of the previous mode pointer to switch
* to.
*/
@@ -926,5 +873,23 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time)
xfree(saved_mode->name);
xfree(saved_mode);
}
+
+ /* If we've enabled/disabled some pipes, we need to reset cloning mode
+ * support.
+ */
+ if (pipes_reconfigured) {
+ if ((pI830->operatingDevices & 0x00ff) &&
+ (pI830->operatingDevices & 0xff00))
+ {
+ pI830->Clone = TRUE;
+ } else {
+ pI830->Clone = FALSE;
+ }
+
+ /* If HW cursor currently showing, reset cursor state */
+ if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn)
+ pI830->CursorInfoRec->ShowCursor(pScrn);
+ }
+
return n;
}
diff --git a/src/i830_sdvo.h b/src/i830_sdvo.h
index d52eb607..52621e03 100644
--- a/src/i830_sdvo.h
+++ b/src/i830_sdvo.h
@@ -66,3 +66,6 @@ i830SDVOPostRestore(ScrnInfoPtr pScrn, int output_index);
Bool
I830DetectSDVODisplays(ScrnInfoPtr pScrn, int output_index);
+
+void
+I830DumpSDVO(ScrnInfoPtr pScrn);
diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c
new file mode 100644
index 00000000..16a8cd83
--- /dev/null
+++ b/src/i830_xf86Modes.c
@@ -0,0 +1,348 @@
+/* $XdotOrg: xserver/xorg/hw/xfree86/common/xf86Mode.c,v 1.10 2006/03/07 16:00:57 libv Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Mode.c,v 1.69 2003/10/08 14:58:28 dawes Exp $ */
+/*
+ * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the copyright holder(s)
+ * and author(s) shall not be used in advertising or otherwise to promote
+ * the sale, use or other dealings in this Software without prior written
+ * authorization from the copyright holder(s) and author(s).
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stddef.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "xf86.h"
+#include "i830.h"
+#include "i830_xf86Modes.h"
+
+/**
+ * @file this file contains symbols from xf86Mode.c and friends that are static
+ * there but we still want to use. We need to come up with better API here.
+ */
+
+/**
+ * Calculates the vertical refresh of a mode.
+ *
+ * Exact copy of xf86Mode.c's.
+ */
+double
+I830ModeVRefresh(DisplayModePtr mode)
+{
+ double refresh = 0.0;
+
+ if (mode->VRefresh > 0.0)
+ refresh = mode->VRefresh;
+ else if (mode->HTotal > 0 && mode->VTotal > 0) {
+ refresh = mode->Clock * 1000.0 / mode->HTotal / mode->VTotal;
+ if (mode->Flags & V_INTERLACE)
+ refresh *= 2.0;
+ if (mode->Flags & V_DBLSCAN)
+ refresh /= 2.0;
+ if (mode->VScan > 1)
+ refresh /= (float)(mode->VScan);
+ }
+ return refresh;
+}
+
+/*
+ * I830xf86SetModeCrtc
+ *
+ * Initialises the Crtc parameters for a mode. The initialisation includes
+ * adjustments for interlaced and double scan modes.
+ *
+ * Exact copy of xf86Mode.c's.
+ */
+void
+I830xf86SetModeCrtc(DisplayModePtr p, int adjustFlags)
+{
+ if ((p == NULL) || ((p->type & M_T_CRTC_C) == M_T_BUILTIN))
+ return;
+
+ p->CrtcHDisplay = p->HDisplay;
+ p->CrtcHSyncStart = p->HSyncStart;
+ p->CrtcHSyncEnd = p->HSyncEnd;
+ p->CrtcHTotal = p->HTotal;
+ p->CrtcHSkew = p->HSkew;
+ p->CrtcVDisplay = p->VDisplay;
+ p->CrtcVSyncStart = p->VSyncStart;
+ p->CrtcVSyncEnd = p->VSyncEnd;
+ p->CrtcVTotal = p->VTotal;
+ if (p->Flags & V_INTERLACE) {
+ if (adjustFlags & INTERLACE_HALVE_V) {
+ p->CrtcVDisplay /= 2;
+ p->CrtcVSyncStart /= 2;
+ p->CrtcVSyncEnd /= 2;
+ p->CrtcVTotal /= 2;
+ }
+ /* Force interlaced modes to have an odd VTotal */
+ /* maybe we should only do this when INTERLACE_HALVE_V is set? */
+ p->CrtcVTotal |= 1;
+ }
+
+ if (p->Flags & V_DBLSCAN) {
+ p->CrtcVDisplay *= 2;
+ p->CrtcVSyncStart *= 2;
+ p->CrtcVSyncEnd *= 2;
+ p->CrtcVTotal *= 2;
+ }
+ if (p->VScan > 1) {
+ p->CrtcVDisplay *= p->VScan;
+ p->CrtcVSyncStart *= p->VScan;
+ p->CrtcVSyncEnd *= p->VScan;
+ p->CrtcVTotal *= p->VScan;
+ }
+ p->CrtcHAdjusted = FALSE;
+ p->CrtcVAdjusted = FALSE;
+
+ /*
+ * XXX
+ *
+ * The following is taken from VGA, but applies to other cores as well.
+ */
+ p->CrtcVBlankStart = min(p->CrtcVSyncStart, p->CrtcVDisplay);
+ p->CrtcVBlankEnd = max(p->CrtcVSyncEnd, p->CrtcVTotal);
+ if ((p->CrtcVBlankEnd - p->CrtcVBlankStart) >= 127) {
+ /*
+ * V Blanking size must be < 127.
+ * Moving blank start forward is safer than moving blank end
+ * back, since monitors clamp just AFTER the sync pulse (or in
+ * the sync pulse), but never before.
+ */
+ p->CrtcVBlankStart = p->CrtcVBlankEnd - 127;
+ /*
+ * If VBlankStart is now > VSyncStart move VBlankStart
+ * to VSyncStart using the maximum width that fits into
+ * VTotal.
+ */
+ if (p->CrtcVBlankStart > p->CrtcVSyncStart) {
+ p->CrtcVBlankStart = p->CrtcVSyncStart;
+ p->CrtcVBlankEnd = min(p->CrtcHBlankStart + 127, p->CrtcVTotal);
+ }
+ }
+ p->CrtcHBlankStart = min(p->CrtcHSyncStart, p->CrtcHDisplay);
+ p->CrtcHBlankEnd = max(p->CrtcHSyncEnd, p->CrtcHTotal);
+
+ if ((p->CrtcHBlankEnd - p->CrtcHBlankStart) >= 63 * 8) {
+ /*
+ * H Blanking size must be < 63*8. Same remark as above.
+ */
+ p->CrtcHBlankStart = p->CrtcHBlankEnd - 63 * 8;
+ if (p->CrtcHBlankStart > p->CrtcHSyncStart) {
+ p->CrtcHBlankStart = p->CrtcHSyncStart;
+ p->CrtcHBlankEnd = min(p->CrtcHBlankStart + 63 * 8, p->CrtcHTotal);
+ }
+ }
+}
+
+/**
+ * Returns true if the given modes should program to the same timings.
+ *
+ * This doesn't use Crtc values, as it might be used on ModeRecs without the
+ * Crtc values set. So, it's assumed that the other numbers are enough.
+ *
+ * This isn't in xf86Modes.c, but it might deserve to be there.
+ */
+Bool
+I830ModesEqual(DisplayModePtr pMode1, DisplayModePtr pMode2)
+{
+ if (pMode1->Clock == pMode2->Clock &&
+ pMode1->HDisplay == pMode2->HDisplay &&
+ pMode1->HSyncStart == pMode2->HSyncStart &&
+ pMode1->HSyncEnd == pMode2->HSyncEnd &&
+ pMode1->HTotal == pMode2->HTotal &&
+ pMode1->HSkew == pMode2->HSkew &&
+ pMode1->VDisplay == pMode2->VDisplay &&
+ pMode1->VSyncStart == pMode2->VSyncStart &&
+ pMode1->VSyncEnd == pMode2->VSyncEnd &&
+ pMode1->VTotal == pMode2->VTotal &&
+ pMode1->VScan == pMode2->VScan &&
+ pMode1->Flags == pMode2->Flags)
+ {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/* exact copy of xf86Mode.c */
+static void
+add(char **p, char *new)
+{
+ *p = xnfrealloc(*p, strlen(*p) + strlen(new) + 2);
+ strcat(*p, " ");
+ strcat(*p, new);
+}
+
+/**
+ * Print out a modeline.
+ *
+ * Convenient VRefresh printing was added, though, compared to xf86Mode.c
+ */
+void
+PrintModeline(int scrnIndex,DisplayModePtr mode)
+{
+ char tmp[256];
+ char *flags = xnfcalloc(1, 1);
+
+ if (mode->HSkew) {
+ snprintf(tmp, 256, "hskew %i", mode->HSkew);
+ add(&flags, tmp);
+ }
+ if (mode->VScan) {
+ snprintf(tmp, 256, "vscan %i", mode->VScan);
+ add(&flags, tmp);
+ }
+ if (mode->Flags & V_INTERLACE) add(&flags, "interlace");
+ if (mode->Flags & V_CSYNC) add(&flags, "composite");
+ if (mode->Flags & V_DBLSCAN) add(&flags, "doublescan");
+ if (mode->Flags & V_BCAST) add(&flags, "bcast");
+ if (mode->Flags & V_PHSYNC) add(&flags, "+hsync");
+ if (mode->Flags & V_NHSYNC) add(&flags, "-hsync");
+ if (mode->Flags & V_PVSYNC) add(&flags, "+vsync");
+ if (mode->Flags & V_NVSYNC) add(&flags, "-vsync");
+ if (mode->Flags & V_PCSYNC) add(&flags, "+csync");
+ if (mode->Flags & V_NCSYNC) add(&flags, "-csync");
+#if 0
+ if (mode->Flags & V_CLKDIV2) add(&flags, "vclk/2");
+#endif
+ xf86DrvMsg(scrnIndex, X_ERROR,
+ "Modeline \"%s\"x%.01f %6.2f %i %i %i %i %i %i %i %i%s\n",
+ mode->name, mode->VRefresh, mode->Clock/1000., mode->HDisplay,
+ mode->HSyncStart, mode->HSyncEnd, mode->HTotal,
+ mode->VDisplay, mode->VSyncStart, mode->VSyncEnd,
+ mode->VTotal, flags);
+ xfree(flags);
+}
+
+#define MODEPREFIX(name) NULL, NULL, name, MODE_OK, M_T_DEFAULT
+#define MODESUFFIX 0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,FALSE,FALSE,0,NULL,0,0.0,0.0
+
+/**
+ * List of VESA established modes, taken from xf86DefaultModes but trimmed down.
+ * (not trimming should be harmless).
+ */
+DisplayModeRec I830xf86DefaultModes[] = {
+/* 640x350 @ 85Hz (VESA) hsync: 37.9kHz */
+ {MODEPREFIX("640x350"),31500, 640,672,736,832,0, 350,382,385,445,0, V_PHSYNC | V_NVSYNC, MODESUFFIX},
+ {MODEPREFIX("320x175"),15750, 320,336,368,416,0, 175,191,192,222,0, V_PHSYNC | V_NVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 640x400 @ 85Hz (VESA) hsync: 37.9kHz */
+ {MODEPREFIX("640x400"),31500, 640,672,736,832,0, 400,401,404,445,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("320x200"),15750, 320,336,368,416,0, 200,200,202,222,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 720x400 @ 85Hz (VESA) hsync: 37.9kHz */
+ {MODEPREFIX("720x400"),35500, 720,756,828,936,0, 400,401,404,446,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("360x200"),17750, 360,378,414,468,0, 200,200,202,223,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 640x480 @ 72Hz (VESA) hsync: 37.9kHz */
+ {MODEPREFIX("640x480"),31500, 640,664,704,832,0, 480,489,491,520,0, V_NHSYNC | V_NVSYNC, MODESUFFIX},
+ {MODEPREFIX("320x240"),15750, 320,332,352,416,0, 240,244,245,260,0, V_NHSYNC | V_NVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 640x480 @ 75Hz (VESA) hsync: 37.5kHz */
+ {MODEPREFIX("640x480"),31500, 640,656,720,840,0, 480,481,484,500,0, V_NHSYNC | V_NVSYNC, MODESUFFIX},
+ {MODEPREFIX("320x240"),15750, 320,328,360,420,0, 240,240,242,250,0, V_NHSYNC | V_NVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 640x480 @ 85Hz (VESA) hsync: 43.3kHz */
+ {MODEPREFIX("640x480"),36000, 640,696,752,832,0, 480,481,484,509,0, V_NHSYNC | V_NVSYNC, MODESUFFIX},
+ {MODEPREFIX("320x240"),18000, 320,348,376,416,0, 240,240,242,254,0, V_NHSYNC | V_NVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 800x600 @ 56Hz (VESA) hsync: 35.2kHz */
+ {MODEPREFIX("800x600"),36000, 800,824,896,1024,0, 600,601,603,625,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("400x300"),18000, 400,412,448,512,0, 300,300,301,312,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 800x600 @ 60Hz (VESA) hsync: 37.9kHz */
+ {MODEPREFIX("800x600"),40000, 800,840,968,1056,0, 600,601,605,628,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("400x300"),20000, 400,420,484,528,0, 300,300,302,314,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 800x600 @ 72Hz (VESA) hsync: 48.1kHz */
+ {MODEPREFIX("800x600"),50000, 800,856,976,1040,0, 600,637,643,666,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("400x300"),25000, 400,428,488,520,0, 300,318,321,333,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 800x600 @ 75Hz (VESA) hsync: 46.9kHz */
+ {MODEPREFIX("800x600"),49500, 800,816,896,1056,0, 600,601,604,625,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("400x300"),24750, 400,408,448,528,0, 300,300,302,312,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 800x600 @ 85Hz (VESA) hsync: 53.7kHz */
+ {MODEPREFIX("800x600"),56300, 800,832,896,1048,0, 600,601,604,631,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("400x300"),28150, 400,416,448,524,0, 300,300,302,315,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1024x768 @ 60Hz (VESA) hsync: 48.4kHz */
+ {MODEPREFIX("1024x768"),65000, 1024,1048,1184,1344,0, 768,771,777,806,0, V_NHSYNC | V_NVSYNC, MODESUFFIX},
+ {MODEPREFIX("512x384"),32500, 512,524,592,672,0, 384,385,388,403,0, V_NHSYNC | V_NVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1024x768 @ 70Hz (VESA) hsync: 56.5kHz */
+ {MODEPREFIX("1024x768"),75000, 1024,1048,1184,1328,0, 768,771,777,806,0, V_NHSYNC | V_NVSYNC, MODESUFFIX},
+ {MODEPREFIX("512x384"),37500, 512,524,592,664,0, 384,385,388,403,0, V_NHSYNC | V_NVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1024x768 @ 75Hz (VESA) hsync: 60.0kHz */
+ {MODEPREFIX("1024x768"),78800, 1024,1040,1136,1312,0, 768,769,772,800,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("512x384"),39400, 512,520,568,656,0, 384,384,386,400,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1024x768 @ 85Hz (VESA) hsync: 68.7kHz */
+ {MODEPREFIX("1024x768"),94500, 1024,1072,1168,1376,0, 768,769,772,808,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("512x384"),47250, 512,536,584,688,0, 384,384,386,404,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1152x864 @ 75Hz (VESA) hsync: 67.5kHz */
+ {MODEPREFIX("1152x864"),108000, 1152,1216,1344,1600,0, 864,865,868,900,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("576x432"),54000, 576,608,672,800,0, 432,432,434,450,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1280x960 @ 60Hz (VESA) hsync: 60.0kHz */
+ {MODEPREFIX("1280x960"),108000, 1280,1376,1488,1800,0, 960,961,964,1000,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("640x480"),54000, 640,688,744,900,0, 480,480,482,500,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1280x960 @ 85Hz (VESA) hsync: 85.9kHz */
+ {MODEPREFIX("1280x960"),148500, 1280,1344,1504,1728,0, 960,961,964,1011,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("640x480"),74250, 640,672,752,864,0, 480,480,482,505,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1280x1024 @ 60Hz (VESA) hsync: 64.0kHz */
+ {MODEPREFIX("1280x1024"),108000, 1280,1328,1440,1688,0, 1024,1025,1028,1066,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("640x512"),54000, 640,664,720,844,0, 512,512,514,533,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1280x1024 @ 75Hz (VESA) hsync: 80.0kHz */
+ {MODEPREFIX("1280x1024"),135000, 1280,1296,1440,1688,0, 1024,1025,1028,1066,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("640x512"),67500, 640,648,720,844,0, 512,512,514,533,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1280x1024 @ 85Hz (VESA) hsync: 91.1kHz */
+ {MODEPREFIX("1280x1024"),157500, 1280,1344,1504,1728,0, 1024,1025,1028,1072,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("640x512"),78750, 640,672,752,864,0, 512,512,514,536,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1600x1200 @ 60Hz (VESA) hsync: 75.0kHz */
+ {MODEPREFIX("1600x1200"),162000, 1600,1664,1856,2160,0, 1200,1201,1204,1250,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("800x600"),81000, 800,832,928,1080,0, 600,600,602,625,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1600x1200 @ 65Hz (VESA) hsync: 81.3kHz */
+ {MODEPREFIX("1600x1200"),175500, 1600,1664,1856,2160,0, 1200,1201,1204,1250,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("800x600"),87750, 800,832,928,1080,0, 600,600,602,625,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1600x1200 @ 70Hz (VESA) hsync: 87.5kHz */
+ {MODEPREFIX("1600x1200"),189000, 1600,1664,1856,2160,0, 1200,1201,1204,1250,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("800x600"),94500, 800,832,928,1080,0, 600,600,602,625,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1600x1200 @ 75Hz (VESA) hsync: 93.8kHz */
+ {MODEPREFIX("1600x1200"),202500, 1600,1664,1856,2160,0, 1200,1201,1204,1250,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("800x600"),101250, 800,832,928,1080,0, 600,600,602,625,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1600x1200 @ 85Hz (VESA) hsync: 106.3kHz */
+ {MODEPREFIX("1600x1200"),229500, 1600,1664,1856,2160,0, 1200,1201,1204,1250,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("800x600"),114750, 800,832,928,1080,0, 600,600,602,625,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1792x1344 @ 60Hz (VESA) hsync: 83.6kHz */
+ {MODEPREFIX("1792x1344"),204800, 1792,1920,2120,2448,0, 1344,1345,1348,1394,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("896x672"),102400, 896,960,1060,1224,0, 672,672,674,697,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1792x1344 @ 75Hz (VESA) hsync: 106.3kHz */
+ {MODEPREFIX("1792x1344"),261000, 1792,1888,2104,2456,0, 1344,1345,1348,1417,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("896x672"),130500, 896,944,1052,1228,0, 672,672,674,708,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1856x1392 @ 60Hz (VESA) hsync: 86.3kHz */
+ {MODEPREFIX("1856x1392"),218300, 1856,1952,2176,2528,0, 1392,1393,1396,1439,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("928x696"),109150, 928,976,1088,1264,0, 696,696,698,719,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1856x1392 @ 75Hz (VESA) hsync: 112.5kHz */
+ {MODEPREFIX("1856x1392"),288000, 1856,1984,2208,2560,0, 1392,1393,1396,1500,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("928x696"),144000, 928,992,1104,1280,0, 696,696,698,750,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1920x1440 @ 60Hz (VESA) hsync: 90.0kHz */
+ {MODEPREFIX("1920x1440"),234000, 1920,2048,2256,2600,0, 1440,1441,1444,1500,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("960x720"),117000, 960,1024,1128,1300,0, 720,720,722,750,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1920x1440 @ 75Hz (VESA) hsync: 112.5kHz */
+ {MODEPREFIX("1920x1440"),297000, 1920,2064,2288,2640,0, 1440,1441,1444,1500,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("960x720"),148500, 960,1032,1144,1320,0, 720,720,722,750,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+
+ /* Terminator */
+ {MODEPREFIX(NULL), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, MODESUFFIX}
+};
diff --git a/src/i830_xf86Modes.h b/src/i830_xf86Modes.h
new file mode 100644
index 00000000..ba7d8209
--- /dev/null
+++ b/src/i830_xf86Modes.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+double
+I830ModeVRefresh(DisplayModePtr mode);
+
+void
+I830xf86SetModeCrtc(DisplayModePtr p, int adjustFlags);
+
+Bool
+I830ModesEqual(DisplayModePtr pMode1, DisplayModePtr pMode2);
+
+void
+PrintModeline(int scrnIndex,DisplayModePtr mode);
+
+extern DisplayModeRec I830xf86DefaultModes[];