diff options
author | Alex Deucher <alex@t41p.hsd1.va.comcast.net> | 2007-09-30 12:02:54 -0400 |
---|---|---|
committer | Alex Deucher <alex@t41p.hsd1.va.comcast.net> | 2007-09-30 12:02:54 -0400 |
commit | 99ceaefa18c6e07b55106cca0ea8996fa73667be (patch) | |
tree | 98e594f98aadd19cf21a62b8f38e055441238bf4 /src/radeon_modes.c | |
parent | d808781d48adf01e80b5bb476bae2d2f599030f1 (diff) |
RADEON: more work on LVDS mode validation and fixups
Hopefully this will fix up the weird mode issues with LVDS and
native and RMX modes, but I can't seem to get quite the right
combo to fix everyone.
Diffstat (limited to 'src/radeon_modes.c')
-rw-r--r-- | src/radeon_modes.c | 103 |
1 files changed, 97 insertions, 6 deletions
diff --git a/src/radeon_modes.c b/src/radeon_modes.c index 51b53665..453f4a8c 100644 --- a/src/radeon_modes.c +++ b/src/radeon_modes.c @@ -120,7 +120,7 @@ static DisplayModePtr RADEONFPNativeMode(xf86OutputPtr output) new->Clock = radeon_output->DotClock; new->Flags = 0; - new->type = M_T_USERDEF | M_T_PREFERRED; + new->type = M_T_DRIVER | M_T_PREFERRED; new->next = NULL; new->prev = NULL; @@ -132,9 +132,101 @@ static DisplayModePtr RADEONFPNativeMode(xf86OutputPtr output) return new; } +/* FP mode initialization routine for using on-chip RMX to scale + */ +int RADEONValidateFPModes(xf86OutputPtr output, char **ppModeName, DisplayModePtr *modeList) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONOutputPrivatePtr radeon_output = output->driver_private; + DisplayModePtr last = NULL; + DisplayModePtr new = NULL; + DisplayModePtr first = NULL; + int count = 0; + int i, width, height; + + + /* add the native mode */ + if (!count) { + first = last = RADEONFPNativeMode(output); + if (first) count = 1; + } + + /* We have a flat panel connected to the primary display, and we + * don't have any DDC info. + */ + for (i = 0; ppModeName[i] != NULL; i++) { + + if (sscanf(ppModeName[i], "%dx%d", &width, &height) != 2) continue; + + /* already added the native mode */ + if (width == radeon_output->PanelXRes && height == radeon_output->PanelYRes) + continue; + + /* Note: We allow all non-standard modes as long as they do not + * exceed the native resolution of the panel. Since these modes + * need the internal RMX unit in the video chips (and there is + * only one per card), this will only apply to the primary head. + */ + if (width < 320 || width > radeon_output->PanelXRes || + height < 200 || height > radeon_output->PanelYRes) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Mode %s is out of range.\n", ppModeName[i]); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Valid modes must be between 320x200-%dx%d\n", + radeon_output->PanelXRes, radeon_output->PanelYRes); + continue; + } + + new = xnfcalloc(1, sizeof(DisplayModeRec)); + new->name = xnfalloc(strlen(ppModeName[i]) + 1); + strcpy(new->name, ppModeName[i]); + new->HDisplay = width; + new->VDisplay = height; + + /* These values are effective values after expansion They are + * not really used to set CRTC registers. + */ + new->HTotal = radeon_output->PanelXRes + radeon_output->HBlank; + new->HSyncStart = radeon_output->PanelXRes + radeon_output->HOverPlus; + new->HSyncEnd = new->HSyncStart + radeon_output->HSyncWidth; + new->VTotal = radeon_output->PanelYRes + radeon_output->VBlank; + new->VSyncStart = radeon_output->PanelYRes + radeon_output->VOverPlus; + new->VSyncEnd = new->VSyncStart + radeon_output->VSyncWidth; + new->Clock = radeon_output->DotClock; + new->Flags |= RADEON_USE_RMX; + + new->type |= M_T_USERDEF; + + new->next = NULL; + new->prev = last; + + if (last) last->next = new; + last = new; + if (!first) first = new; + + count++; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Valid mode using on-chip RMX: %s\n", new->name); + } + + + /* Close the doubly-linked mode list, if we found any usable modes */ + if (last) { + last->next = NULL; //first; + first->prev = NULL; //last; + *modeList = first; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Total number of valid FP mode(s) found: %d\n", count); + + return count; +} + DisplayModePtr RADEONProbeOutputModes(xf86OutputPtr output) { + ScrnInfoPtr pScrn = output->scrn; RADEONOutputPrivatePtr radeon_output = output->driver_private; xf86MonPtr edid_mon; DisplayModePtr modes = NULL; @@ -160,12 +252,11 @@ RADEONProbeOutputModes(xf86OutputPtr output) xf86OutputSetEDID (output, edid_mon); modes = xf86OutputGetEDIDModes (output); - return modes; - } else { - /* add native panel mode */ - modes = RADEONFPNativeMode(output); - return modes; } + if (modes == NULL) { + RADEONValidateFPModes(output, pScrn->display->modes, &modes); + } + return modes; } } |