diff options
author | airlied <airlied@optimus.localdomain> | 2006-11-18 15:48:02 +1100 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2006-12-03 16:16:15 +1100 |
commit | eb17c9aed2144701ad7bd1042b2905446e4d708a (patch) | |
tree | b68ed887137ab883607ebafa0aa84f190948628b /src/radeon_modes.c | |
parent | 941b5120916ebff69ec0ee4ca7a46105d5306e5d (diff) |
move radeon over to not using X's mode management like the intel driver.
this builds and at least seems to pick a mode.. might be near to hooking
up randr1.2 soon
Diffstat (limited to 'src/radeon_modes.c')
-rw-r--r-- | src/radeon_modes.c | 240 |
1 files changed, 238 insertions, 2 deletions
diff --git a/src/radeon_modes.c b/src/radeon_modes.c index 964ac5b8..694b2ed5 100644 --- a/src/radeon_modes.c +++ b/src/radeon_modes.c @@ -52,6 +52,15 @@ /* DDC support */ #include "xf86DDC.h" +void +RADEONGetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y) +{ + ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; + + *x = pScrn->virtualX; + *y = pScrn->virtualY; +} + void RADEONSetPitch (ScrnInfoPtr pScrn) { int dummy = pScrn->virtualX; @@ -284,7 +293,7 @@ static DisplayModePtr RADEONFPNativeMode(ScrnInfoPtr pScrn) /* FP mode initialization routine for using on-chip RMX to scale */ -int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName) +int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName, DisplayModePtr modeList) { RADEONInfoPtr info = RADEONPTR(pScrn); DisplayModePtr last = NULL; @@ -367,7 +376,7 @@ int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName) } /* add in all default vesa modes smaller than panel size, used for randr*/ - for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) { + for (p = modeList; p && p->next; p = p->next->next) { if ((p->HDisplay <= info->PanelXRes) && (p->VDisplay <= info->PanelYRes)) { tmp = first; while (tmp) { @@ -580,3 +589,230 @@ int RADEONValidateMergeModes(ScrnInfoPtr pScrn1) } return modesFound; } + +void +RADEONProbeOutputModes(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + int i; + DisplayModePtr ddc_modes, mode; + + + for (i = 0; i < RADEON_MAX_CONNECTOR; i++) { + + while(pRADEONEnt->PortInfo[i]->probed_modes != NULL) { + xf86DeleteMode(&pRADEONEnt->PortInfo[i]->probed_modes, + pRADEONEnt->PortInfo[i]->probed_modes); + } + + RADEONConnectorFindMonitor(pScrn, i); + + /* okay we got DDC info */ + if (pRADEONEnt->PortInfo[i]->MonInfo) { + /* Debug info for now, at least */ + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID for output %d\n", i); + xf86PrintEDID(pRADEONEnt->PortInfo[i]->MonInfo); + + ddc_modes = RADEONGetDDCModes(pScrn, pRADEONEnt->PortInfo[i]->MonInfo); + + for (mode = ddc_modes; mode != NULL; mode = mode->next) { + if (mode->Flags & V_DBLSCAN) { + if ((mode->CrtcHDisplay >= 1024) || (mode->CrtcVDisplay >= 768)) + mode->status = MODE_CLOCK_RANGE; + } + } + RADEONxf86PruneInvalidModes(pScrn, &ddc_modes, TRUE); + + /* do some physcial size stuff */ + } + + + if (pRADEONEnt->PortInfo[i]->probed_modes == NULL) { + MonRec fixed_mon; + DisplayModePtr modes; + + switch(pRADEONEnt->PortInfo[i]->MonType) { + case MT_CRT: + case MT_DFP: + + /* We've got a potentially-connected monitor that we can't DDC. Return a + * fixed set of VESA plus user modes for a presumed multisync monitor with + * some reasonable limits. + */ + fixed_mon.nHsync = 1; + fixed_mon.hsync[0].lo = 31.0; + fixed_mon.hsync[0].hi = 100.0; + fixed_mon.nVrefresh = 1; + fixed_mon.vrefresh[0].lo = 50.0; + fixed_mon.vrefresh[0].hi = 70.0; + + modes = RADEONxf86DuplicateModes(pScrn, pScrn->monitor->Modes); + RADEONxf86ValidateModesSync(pScrn, modes, &fixed_mon); + RADEONxf86PruneInvalidModes(pScrn, &modes, TRUE); + /* fill out CRT of FP mode table */ + pRADEONEnt->PortInfo[i]->probed_modes = modes; + break; + + case MT_LCD: + RADEONValidateFPModes(pScrn, pScrn->display->modes, pRADEONEnt->PortInfo[i]->probed_modes); + break; + default: + break; + } + } + + if (pRADEONEnt->PortInfo[i]->probed_modes) { + RADEONxf86ValidateModesUserConfig(pScrn, + pRADEONEnt->PortInfo[i]->probed_modes); + RADEONxf86PruneInvalidModes(pScrn, &pRADEONEnt->PortInfo[i]->probed_modes, + FALSE); + } + + + for (mode = pRADEONEnt->PortInfo[i]->probed_modes; mode != NULL; + mode = mode->next) + { + /* The code to choose the best mode per pipe later on will require + * VRefresh to be set. + */ + mode->VRefresh = RADEONxf86ModeVRefresh(mode); + RADEONxf86SetModeCrtc(mode, INTERLACE_HALVE_V); + +#ifdef DEBUG_REPROBE + PrintModeline(pScrn->scrnIndex, mode); +#endif + } + } +} + + +/** + * Constructs pScrn->modes from the output mode lists. + * + * Currently it only takes one output's mode list and stuffs it into the + * XFree86 DDX mode list while trimming it for root window size. + * + * This should be obsoleted by RandR 1.2 hopefully. + */ +static void +RADEON_set_xf86_modes_from_outputs(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + DisplayModePtr saved_mode, last; + int originalVirtualX, originalVirtualY; + int i; + + /* 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 = info->currentMode; + if (saved_mode != NULL) { + RADEONxf86DeleteModeFromList(&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 an arbitrary output. + * pScrn->modes should only be used for XF86VidMode now, which we don't + * care about enough to make some sort of unioned list. + */ + for (i = 0; i < RADEON_MAX_CONNECTOR; i++) { + if (pRADEONEnt->PortInfo[i]->probed_modes != NULL) { + pScrn->modes = + RADEONxf86DuplicateModes(pScrn, pRADEONEnt->PortInfo[i]->probed_modes); + break; + } + } + + RADEONGetOriginalVirtualSize(pScrn, &originalVirtualX, &originalVirtualY); + + /* Disable modes in the XFree86 DDX list that are larger than the current + * virtual size. + */ + RADEONxf86ValidateModesSize(pScrn, pScrn->modes, + originalVirtualX, originalVirtualY, + pScrn->displayWidth); + + /* Strip out anything that we threw out for virtualX/Y. */ + RADEONxf86PruneInvalidModes(pScrn, &pScrn->modes, TRUE); + + if (pScrn->modes == NULL) { + FatalError("No modes left for XFree86 DDX\n"); + } + + pScrn->currentMode = pScrn->modes; + + xf86SetDpi(pScrn, 0, 0); + info->RADEONDPIVX = pScrn->virtualX; + info->RADEONDPIVY = pScrn->virtualY; + + /* For some reason, pScrn->modes is circular, unlike the other mode lists. + * How great is that? + */ + last = RADEONGetModeListTail(pScrn->modes); + last->next = pScrn->modes; + pScrn->modes->prev = last; + + /* 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. + */ + info->savedCurrentMode = saved_mode; +} + +/** + * Takes the output mode lists and decides the default root window size + * and framebuffer pitch. + */ +static void +RADEON_set_default_screen_size(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + int maxX = -1, maxY = -1; + int i; + + /* Set up a virtual size that will cover any clone mode we'd want to + * set for the currently-connected outputs. + */ + for (i = 0; i < RADEON_MAX_CONNECTOR; i++) { + DisplayModePtr mode; + + for (mode = pRADEONEnt->PortInfo[i]->probed_modes; mode != NULL; + mode = mode->next) + { + if (mode->HDisplay > maxX) + maxX = mode->HDisplay; + if (mode->VDisplay > maxY) + maxY = mode->VDisplay; + } + } + /* let the user specify a bigger virtual size if they like */ + if (pScrn->display->virtualX > maxX) + maxX = pScrn->display->virtualX; + if (pScrn->display->virtualY > maxY) + maxY = pScrn->display->virtualY; + pScrn->virtualX = maxX; + pScrn->virtualY = maxY; + pScrn->displayWidth = (maxX + 63) & ~63; +} + + + +int RADEONValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) +{ + RADEONProbeOutputModes(pScrn); + + if (first_time) + { + RADEON_set_default_screen_size(pScrn); + } + + RADEON_set_xf86_modes_from_outputs(pScrn); + return 1; +} |