diff options
-rw-r--r-- | src/Makefile.am | 5 | ||||
-rw-r--r-- | src/i830.h | 1 | ||||
-rw-r--r-- | src/i830_display.c | 5 | ||||
-rw-r--r-- | src/i830_modes.c | 297 | ||||
-rw-r--r-- | src/i830_sdvo.h | 3 | ||||
-rw-r--r-- | src/i830_xf86Modes.c | 348 | ||||
-rw-r--r-- | src/i830_xf86Modes.h | 40 |
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 \ @@ -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[]; |