Replace xf86ValidateModes usage with a set of custom validators and pruning.

This moves us to maintaining MonPtrs per pipe instead of using the EDID
structure "xf86MonPtr", which is closer to what we want to be looking at when
doing validation.  The new validation isn't enough yet -- particularly, we
aren't importing and validating the custom modelines to the pipes when
applicable, but this will be easier than (for example) trying to make flat
panel modes pass xf86ValidateModes through various gross hacks.

Hotplug turn-on/off also happens at SwitchMode time now, instead of at randr
probe time.
This commit is contained in:
Eric Anholt 2006-06-28 13:10:02 +02:00
parent 9fbd3d8f4b
commit 367f69f8e7
5 changed files with 467 additions and 171 deletions

View File

@ -227,6 +227,10 @@ typedef struct _I830Rec {
int fixedPipe;
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;
Bool Clone;
int CloneRefresh;
@ -401,8 +405,7 @@ typedef struct _I830Rec {
int availablePipes;
/* [0] is display plane A, [1] is display plane B. */
int planeEnabled[MAX_DISPLAY_PIPES];
xf86MonPtr pipeMon[MAX_DISPLAY_PIPES];
DisplayModePtr pipeModes[MAX_DISPLAY_PIPES];
MonPtr pipeMon[MAX_DISPLAY_PIPES];
DisplayModeRec pipeCurMode[MAX_DISPLAY_PIPES];
/* Driver phase/state information */

View File

@ -268,11 +268,12 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe)
/* If we've got a list of modes probed for the device, find the best match
* in there to the requested mode.
*/
if (pI830->pipeModes[pipe] != NULL) {
if (pI830->pipeMon[pipe] != NULL) {
DisplayModePtr pBest = NULL, pScan;
assert(pScan->VRefresh != 0.0);
for (pScan = pI830->pipeModes[pipe]; pScan != NULL; pScan = pScan->next)
for (pScan = pI830->pipeMon[pipe]->Modes; pScan != NULL;
pScan = pScan->next)
{
/* Reject if it's larger than the desired mode. */
if (pScan->HDisplay > pMode->HDisplay ||
@ -284,9 +285,20 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe)
pBest = pScan;
continue;
}
/* Find if it's closer than the current best option */
if ((pScan->HDisplay >= pBest->HDisplay &&
pScan->HDisplay >= pBest->HDisplay) ||
/* Find if it's closer to the right size than the current best
* option.
*/
if (pScan->HDisplay >= pBest->HDisplay &&
pScan->VDisplay >= pBest->VDisplay)
{
pBest = pScan;
continue;
}
/* Find if it's still closer to the right refresh than the current
* best resolution.
*/
if (pScan->HDisplay == pBest->HDisplay &&
pScan->VDisplay == pBest->VDisplay &&
(fabs(pScan->VRefresh - pMode->VRefresh) <
fabs(pBest->VRefresh - pMode->VRefresh)))
{
@ -801,6 +813,29 @@ 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);
/* If we might have enabled/disabled some pipes, we need to reset
* cloning mode support.
*/
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);
}
i830DisableUnusedFunctions(pScrn);
planeA = INREG(DSPACNTR);

View File

@ -47,6 +47,7 @@
#include "xf86.h"
#include "i830.h"
#include "i830_display.h"
#include "i830_xf86Modes.h"
#include <randrstr.h>
@ -247,7 +248,7 @@ I830GetVESAEstablishedMode(ScrnInfoPtr pScrn, int i)
}
static DisplayModePtr
I830GetDDCModes(ScrnInfoPtr pScrn, xf86MonPtr ddc)
i830GetDDCModes(ScrnInfoPtr pScrn, xf86MonPtr ddc)
{
DisplayModePtr last = NULL;
DisplayModePtr new = NULL;
@ -487,9 +488,11 @@ i830GetLVDSModes(ScrnInfoPtr pScrn, char **ppModeName)
/* If the user hasn't specified modes, add the native mode */
if (!count) {
first = last = i830FPNativeMode(pScrn);
if (first)
new = i830FPNativeMode(pScrn);
if (first) {
I830xf86SortModes(new, &first, &last);
count = 1;
}
}
/* add in all default vesa modes smaller than panel size, used for randr */
@ -507,14 +510,7 @@ i830GetLVDSModes(ScrnInfoPtr pScrn, char **ppModeName)
else
new->type |= M_T_DEFAULT;
new->next = NULL;
new->prev = last;
if (last)
last->next = new;
last = new;
if (!first)
first = new;
I830xf86SortModes(new, &first, &last);
count++;
}
@ -546,9 +542,6 @@ I830InjectProbedModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList,
for (addMode = addModes; addMode != NULL; addMode = addMode->next) {
DisplayModePtr pNew;
/* XXX: Do we need to check if modeList already contains the same mode?
*/
pNew = I830DuplicateMode(addMode);
#if 0
/* If the user didn't specify any modes, mark all modes as M_T_USERDEF
@ -580,6 +573,102 @@ I830InjectProbedModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList,
return count;
}
static DisplayModePtr
i830GetModeListTail(DisplayModePtr pModeList)
{
DisplayModePtr last;
if (pModeList == NULL)
return NULL;
for (last = pModeList; last->next != NULL; last = last->next)
;
return last;
}
static MonPtr
i830GetDDCMonitor(ScrnInfoPtr pScrn, I2CBusPtr pDDCBus)
{
xf86MonPtr ddc;
MonPtr mon;
int i;
ddc = xf86DoEDID_DDC2(pScrn->scrnIndex, pDDCBus);
if (ddc == NULL)
return NULL;
mon = xnfcalloc(1, sizeof(*mon));
mon->Modes = i830GetDDCModes(pScrn, ddc);
mon->Last = i830GetModeListTail(mon->Modes);
mon->DDC = ddc;
for (i = 0; i < DET_TIMINGS; i++) {
struct detailed_monitor_section *det_mon = &ddc->det_mon[i];
switch (ddc->det_mon[i].type) {
case DS_RANGES:
mon->hsync[mon->nHsync].lo = det_mon->section.ranges.min_h;
mon->hsync[mon->nHsync].hi = det_mon->section.ranges.max_h;
mon->nHsync++;
mon->vrefresh[mon->nVrefresh].lo = det_mon->section.ranges.min_v;
mon->vrefresh[mon->nVrefresh].hi = det_mon->section.ranges.max_v;
mon->nVrefresh++;
break;
default:
/* We probably don't care about trying to contruct ranges around
* modes specified by DDC.
*/
break;
}
}
return mon;
}
static MonPtr
i830GetLVDSMonitor(ScrnInfoPtr pScrn)
{
MonPtr mon;
mon = xnfcalloc(1, sizeof(*mon));
mon->Modes = i830GetLVDSModes(pScrn, pScrn->display->modes);
mon->Last = i830GetModeListTail(mon->Modes);
return mon;
}
static MonPtr
i830GetConfiguredMonitor(ScrnInfoPtr pScrn)
{
MonPtr mon;
mon = xnfcalloc(1, sizeof(*mon));
memcpy(mon, pScrn->monitor, sizeof(*mon));
if (pScrn->monitor->id != NULL)
mon->id = xnfstrdup(pScrn->monitor->id);
if (pScrn->monitor->vendor != NULL)
mon->vendor = xnfstrdup(pScrn->monitor->vendor);
if (pScrn->monitor->model != NULL)
mon->model = xnfstrdup(pScrn->monitor->model);
return mon;
}
static void
i830FreeMonitor(ScrnInfoPtr pScrn, MonPtr mon)
{
while (mon->Modes != NULL)
xf86DeleteMode(&mon->Modes, mon->Modes);
xfree(mon->id);
xfree(mon->vendor);
xfree(mon->model);
xfree(mon->DDC);
xfree(mon);
}
/**
* Performs probing of modes available on the output connected to the given
* pipe.
@ -596,11 +685,7 @@ I830ReprobePipeModeList(ScrnInfoPtr pScrn, int pipe)
int i;
int outputs;
DisplayModePtr pMode;
Bool had_modes;
had_modes = (pI830->pipeModes[pipe] != NULL);
while (pI830->pipeModes[pipe] != NULL)
xf86DeleteMode(&pI830->pipeModes[pipe], pI830->pipeModes[pipe]);
MonPtr old_mon = pI830->pipeMon[pipe];
if (pipe == 0)
outputs = pI830->operatingDevices & 0xff;
@ -631,45 +716,87 @@ I830ReprobePipeModeList(ScrnInfoPtr pScrn, int pipe)
return;
if (outputs & PIPE_LFP) {
pI830->pipeMon[pipe] = NULL; /* XXX */
pI830->pipeModes[pipe] = i830GetLVDSModes(pScrn,
pScrn->display->modes);
pI830->pipeMon[pipe] = i830GetLVDSMonitor(pScrn);
} else if (pI830->output[output_index].pDDCBus != NULL) {
/* XXX: Free the mon */
pI830->pipeMon[pipe] = xf86DoEDID_DDC2(pScrn->scrnIndex,
pI830->output[output_index].pDDCBus);
pI830->pipeModes[pipe] = I830GetDDCModes(pScrn,
pI830->pipeMon[pipe]);
for (pMode = pI830->pipeModes[pipe]; pMode != NULL; pMode = pMode->next)
{
I830xf86SetModeCrtc(pMode, INTERLACE_HALVE_V);
pI830->pipeMon[pipe] =
i830GetDDCMonitor(pScrn, pI830->output[output_index].pDDCBus);
}
/* If DDC didn't work (or the flat panel equivalent), then see if we can
* detect if a monitor is at least plugged in. If we can't tell that one
* is plugged in, then assume that it is.
*/
if (pI830->pipeMon[pipe] == NULL) {
switch (pI830->output[output_index].type) {
case I830_OUTPUT_SDVO:
if (I830DetectSDVODisplays(pScrn, output_index))
pI830->pipeMon[pipe] = i830GetConfiguredMonitor(pScrn);
break;
case I830_OUTPUT_ANALOG:
/* Do a disruptive detect if necessary, since we want to be sure we
* know if a monitor is attached, and this detect process should be
* infrequent.
*/
if (i830DetectCRT(pScrn, TRUE))
pI830->pipeMon[pipe] = i830GetConfiguredMonitor(pScrn);
break;
default:
pI830->pipeMon[pipe] = i830GetConfiguredMonitor(pScrn);
break;
}
if (had_modes && pI830->pipeModes[pipe] == NULL) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Failed to DDC pipe %d, disabling output\n", pipe);
if (pipe == 0)
pI830->operatingDevices &= ~0x00ff;
else
pI830->operatingDevices &= ~0xff00;
}
} else {
ErrorF("don't know how to get modes for this device.\n");
}
/* 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);
if (pI830->pipeMon[pipe] != NULL) {
int minclock, maxclock;
switch (pI830->output[output_index].type) {
case I830_OUTPUT_SDVO:
minclock = 25000;
maxclock = 165000;
case I830_OUTPUT_LVDS:
case I830_OUTPUT_ANALOG:
default:
minclock = 25000;
maxclock = 400000;
}
i830xf86ValidateModesFlags(pScrn, pI830->pipeMon[pipe]->Modes,
V_INTERLACE);
i830xf86ValidateModesClocks(pScrn, pI830->pipeMon[pipe]->Modes,
&minclock, &maxclock, 1);
i830xf86PruneInvalidModes(pScrn, &pI830->pipeMon[pipe]->Modes, TRUE);
for (pMode = pI830->pipeMon[pipe]->Modes; pMode != NULL;
pMode = pMode->next)
{
/* The code to choose the best mode per pipe later on will require
* VRefresh to be set.
*/
pMode->VRefresh = I830ModeVRefresh(pMode);
I830xf86SetModeCrtc(pMode, INTERLACE_HALVE_V);
#ifdef DEBUG_REPROBE
PrintModeline(pScrn->scrnIndex, pMode);
PrintModeline(pScrn->scrnIndex, pMode);
#endif
}
}
if (old_mon != NULL && pI830->pipeMon[pipe] == NULL) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Failed to probe output on pipe %d, disabling output at next "
"mode switch\n", pipe);
if (pipe == 0)
pI830->operatingDevices &= ~0x00ff;
else
pI830->operatingDevices &= ~0xff00;
}
if (old_mon != NULL)
i830FreeMonitor(pScrn, old_mon);
}
/**
@ -720,10 +847,8 @@ int
I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time)
{
I830Ptr pI830 = I830PTR(pScrn);
ClockRangePtr clockRanges;
int n, pipe;
DisplayModePtr saved_mode, availModes = NULL;
int saved_virtualX = 0, saved_virtualY = 0, saved_displayWidth = 0;
int pipe;
DisplayModePtr saved_mode, last;
Bool pipes_reconfigured = FALSE;
int originalVirtualX, originalVirtualY;
@ -738,7 +863,7 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time)
if ((pI830->operatingDevices & 0xff) == PIPE_NONE) {
pI830->operatingDevices |= PIPE_CRT;
I830ReprobePipeModeList(pScrn, 0);
if (pI830->pipeModes[0] == NULL) {
if (pI830->pipeMon[0] == NULL) {
/* No new output found. */
pI830->operatingDevices &= ~PIPE_CRT;
} else {
@ -751,7 +876,7 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time)
} else if (((pI830->operatingDevices >> 8) & 0xff) == PIPE_NONE) {
pI830->operatingDevices |= PIPE_CRT << 8;
I830ReprobePipeModeList(pScrn, 1);
if (pI830->pipeModes[1] == NULL) {
if (pI830->pipeMon[1] == NULL) {
/* No new output found. */
pI830->operatingDevices &= ~(PIPE_CRT << 8);
} else {
@ -764,20 +889,105 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time)
}
}
/* 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, &availModes, pI830->pipeModes[0]);
}
if (pI830->pipeModes[1] != NULL) {
I830InjectProbedModes(pScrn, &availModes, pI830->pipeModes[1]);
if ((pI830->pipeMon[0] == NULL || pI830->pipeMon[0]->Modes == NULL) &&
(pI830->pipeMon[1] == NULL || pI830->pipeMon[1]->Modes == NULL))
{
FatalError("No modes found on either pipe\n");
}
/*
if (first_time) {
int maxX = -1, maxY = -1;
/* Set up a virtual size that will cover any clone mode we'd want to set
* for either of the two pipes.
*/
for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) {
MonPtr mon = pI830->pipeMon[pipe];
DisplayModePtr mode;
if (mon == NULL)
continue;
for (mode = mon->Modes; mode != NULL; mode = mode->next) {
if (mode->HDisplay > maxX)
maxX = mode->HDisplay;
if (mode->VDisplay > maxY)
maxY = mode->VDisplay;
}
}
pScrn->virtualX = maxX;
pScrn->virtualY = maxY;
pScrn->displayWidth = (maxX + 63) & ~63;
}
I830GetOriginalVirtualSize(pScrn, &originalVirtualX, &originalVirtualY);
/* Disable modes that are larger than the virtual size we decided on
* initially.
*/
if (!first_time) {
for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) {
MonPtr mon = pI830->pipeMon[pipe];
DisplayModePtr mode;
if (mon == NULL)
continue;
for (mode = mon->Modes; mode != NULL; mode = mode->next)
{
if (mode->HDisplay > originalVirtualX)
mode->status = MODE_VIRTUAL_X;
if (mode->VDisplay > originalVirtualY)
mode->status = MODE_VIRTUAL_Y;
}
}
}
/* Remove the current mode from the modelist if we're re-validating, so we
* can find a new mode to map ourselves to afterwards.
*/
saved_mode = pI830->currentMode;
if (saved_mode != NULL) {
I830xf86DeleteModeFromList(&pScrn->modes, saved_mode);
}
/* Clear any existing modes from pScrn->modes */
while (pScrn->modes != NULL)
xf86DeleteMode(&pScrn->modes, pScrn->modes);
/* Set pScrn->modes to the mode list for the an arbitrary head.
* pScrn->modes should only be used for XF86VidMode now, which we don't
* care about enough to make some sort of unioned list.
*/
if (pI830->pipeMon[1] != NULL) {
I830InjectProbedModes(pScrn, &pScrn->modes, pI830->pipeMon[1]->Modes);
} else {
I830InjectProbedModes(pScrn, &pScrn->modes, pI830->pipeMon[0]->Modes);
}
if (pScrn->modes == NULL) {
FatalError("No modes found\n");
}
/* Don't let pScrn->modes have modes larger than the max root window size.
* We don't really care about the monitors having it, particularly since we
* eventually want randr to be able to move to those sizes.
*/
i830xf86ValidateModesSize(pScrn, pScrn->modes,
originalVirtualX, originalVirtualY,
pScrn->displayWidth);
/* Strip out anything bad that we threw out for virtualX. */
i830xf86PruneInvalidModes(pScrn, &pScrn->modes, TRUE);
/* For some reason, pScrn->modes is circular, unlike the other mode lists.
* How great is that?
*/
last = i830GetModeListTail(pScrn->modes);
last->next = pScrn->modes;
pScrn->modes->prev = last;
#if 0
/* XXX: do I need this any more? Maybe XF86VidMode uses it?
* Set up the ClockRanges, which describe what clock ranges are available,
* and what sort of modes they can be used for.
*/
@ -788,62 +998,7 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time)
clockRanges->clockIndex = -1; /* programmable */
clockRanges->interlaceAllowed = TRUE; /* XXX check this */
clockRanges->doubleScanAllowed = FALSE; /* XXX check this */
/* Remove the current mode from the modelist if we're re-validating, so we
* can find a new mode to map ourselves to afterwards.
*/
saved_mode = pI830->currentMode;
if (saved_mode != NULL) {
I830xf86DeleteModeFromList(&pScrn->modes, saved_mode);
}
if (!first_time) {
saved_virtualX = pScrn->virtualX;
saved_virtualY = pScrn->virtualY;
saved_displayWidth = pScrn->displayWidth;
}
I830GetOriginalVirtualSize(pScrn, &originalVirtualX, &originalVirtualY);
/* Take the pScrn->monitor->Modes we've accumulated and validate them into
* pScrn->modes.
* XXX: Should set up a scrp->monitor->DDC covering the union of the
* capabilities of our pipes.
*/
n = xf86ValidateModes(pScrn,
availModes, /* availModes */
pScrn->display->modes, /* modeNames */
clockRanges, /* clockRanges */
!first_time ? &pScrn->displayWidth : NULL, /* linePitches */
320, /* minPitch */
MAX_DISPLAY_PITCH, /* maxPitch */
64 * pScrn->bitsPerPixel, /* pitchInc */
200, /* minHeight */
MAX_DISPLAY_HEIGHT, /* maxHeight */
originalVirtualX, /* virtualX maximum */
originalVirtualY, /* virtualY maximum */
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;
pScrn->virtualY = saved_virtualY;
pScrn->displayWidth = saved_displayWidth;
}
/* Need to do xf86CrtcForModes so any user-configured modes are valid for
* non-LVDS.
*/
xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
xf86PruneDriverModes(pScrn);
#endif
#if DEBUG_REPROBE
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Modes post revalidate\n");
@ -858,49 +1013,12 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time)
} while (0);
#endif
/* Try to find the closest equivalent of the previous mode pointer to switch
* to.
/* Save a pointer to the previous current mode. We can't reset
* pScrn->currentmode, because we rely on xf86SwitchMode's shortcut not
* happening so we can hot-enable devices at SwitchMode. We'll notice this
* case at SwitchMode and free the saved mode.
*/
if (saved_mode != NULL) {
DisplayModePtr pBestMode = NULL, pMode;
pI830->savedCurrentMode = saved_mode;
/* XXX: Is finding a matching x/y res enough? probably not. */
for (pMode = pScrn->modes; ; pMode = pMode->next) {
if (pMode->HDisplay == saved_mode->HDisplay &&
pMode->VDisplay == saved_mode->VDisplay)
{
ErrorF("found matching mode %p\n", pMode);
pBestMode = pMode;
}
if (pMode->next == pScrn->modes)
break;
}
if (pBestMode != NULL)
xf86SwitchMode(pScrn->pScreen, pBestMode);
else
FatalError("No suitable modes after re-probe\n");
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;
return 1; /* XXX */
}

View File

@ -238,6 +238,126 @@ PrintModeline(int scrnIndex,DisplayModePtr mode)
xfree(flags);
}
/**
* Marks as bad any modes with unsupported flags.
*
* \param modeList doubly-linked or circular list of modes.
* \param flags flags supported by the driver.
*
* \bug only V_INTERLACE and V_DBLSCAN are supported. Is that enough?
*
* This is not in xf86Modes.c, but would be part of the proposed new API.
*/
void
i830xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
int flags)
{
DisplayModePtr mode;
for (mode = modeList; mode != NULL; mode = mode->next) {
if (mode->Flags & V_INTERLACE && !(flags & V_INTERLACE))
mode->status = MODE_NO_INTERLACE;
if (mode->Flags & V_DBLSCAN && !(flags & V_DBLSCAN))
mode->status = MODE_NO_DBLESCAN;
}
}
/**
* Marks as bad any modes extending beyond the given max X, Y, or pitch.
*
* \param modeList doubly-linked or circular list of modes.
*
* This is not in xf86Modes.c, but would be part of the proposed new API.
*/
void
i830xf86ValidateModesSize(ScrnInfoPtr pScrn, DisplayModePtr modeList,
int maxX, int maxY, int maxPitch)
{
DisplayModePtr mode;
for (mode = modeList; mode != NULL; mode = mode->next) {
if (maxPitch > 0 && mode->HDisplay > maxPitch)
mode->status = MODE_BAD_WIDTH;
if (maxX > 0 && mode->HDisplay > maxX)
mode->status = MODE_VIRTUAL_X;
if (maxY > 0 && mode->VDisplay > maxY)
mode->status = MODE_VIRTUAL_Y;
if (mode->next == modeList)
break;
}
}
/**
* Marks as bad any modes extending beyond outside of the given clock ranges.
*
* \param modeList doubly-linked or circular list of modes.
* \param min pointer to minimums of clock ranges
* \param max pointer to maximums of clock ranges
* \param n_ranges number of ranges.
*
* This is not in xf86Modes.c, but would be part of the proposed new API.
*/
void
i830xf86ValidateModesClocks(ScrnInfoPtr pScrn, DisplayModePtr modeList,
int *min, int *max, int n_ranges)
{
DisplayModePtr mode;
int i;
for (mode = modeList; mode != NULL; mode = mode->next) {
Bool good = FALSE;
for (i = 0; i < n_ranges; i++) {
if (mode->Clock >= min[i] && mode->Clock <= max[i]) {
good = TRUE;
break;
}
}
if (!good)
mode->status = MODE_CLOCK_RANGE;
}
}
/**
* Frees any modes from the list with a status other than MODE_OK.
*
* \param modeList pointer to a doubly-linked or circular list of modes.
* \param verbose determines whether the reason for mode invalidation is
* printed.
*
* This is not in xf86Modes.c, but would be part of the proposed new API.
*/
void
i830xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList,
Bool verbose)
{
DisplayModePtr mode;
for (mode = *modeList; mode != NULL;) {
DisplayModePtr next = mode->next;
if (mode->status != MODE_OK) {
if (verbose) {
char *type = "";
if (mode->type & M_T_BUILTIN)
type = "built-in ";
else if (mode->type & M_T_DEFAULT)
type = "default ";
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Not using %smode \"%s\" (%s)\n", type, mode->name,
xf86ModeStatusToString(mode->status));
}
xf86DeleteMode(modeList, mode);
}
if (next == *modeList)
break;
mode = next;
}
}
#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

View File

@ -34,6 +34,26 @@ I830xf86SetModeCrtc(DisplayModePtr p, int adjustFlags);
Bool
I830ModesEqual(DisplayModePtr pMode1, DisplayModePtr pMode2);
void
i830xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
int flags);
void
i830xf86ValidateModesClocks(ScrnInfoPtr pScrn, DisplayModePtr modeList,
int *min, int *max, int n_ranges);
void
i830xf86ValidateModesSize(ScrnInfoPtr pScrn, DisplayModePtr modeList,
int maxX, int maxY, int maxPitch);
void
i830xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList,
Bool verbose);
void
i830xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
int flags);
void
PrintModeline(int scrnIndex,DisplayModePtr mode);