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 | |
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.
-rw-r--r-- | src/radeon_modes.c | 103 | ||||
-rw-r--r-- | src/radeon_output.c | 37 |
2 files changed, 120 insertions, 20 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; } } diff --git a/src/radeon_output.c b/src/radeon_output.c index 6ece28ad..fd94266c 100644 --- a/src/radeon_output.c +++ b/src/radeon_output.c @@ -658,7 +658,7 @@ radeon_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) pMode->VDisplay > radeon_output->PanelYRes) return MODE_PANEL; } - + return MODE_OK; } @@ -668,28 +668,37 @@ radeon_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, { RADEONOutputPrivatePtr radeon_output = output->driver_private; + if (radeon_output->MonType == MT_LCD) { + adjusted_mode->HTotal = radeon_output->PanelXRes + radeon_output->HBlank; + adjusted_mode->HSyncStart = radeon_output->PanelXRes + radeon_output->HOverPlus; + adjusted_mode->HSyncEnd = adjusted_mode->HSyncStart + radeon_output->HSyncWidth; + adjusted_mode->VTotal = radeon_output->PanelYRes + radeon_output->VBlank; + adjusted_mode->VSyncStart = radeon_output->PanelYRes + radeon_output->VOverPlus; + adjusted_mode->VSyncEnd = adjusted_mode->VSyncStart + radeon_output->VSyncWidth; + adjusted_mode->Clock = radeon_output->DotClock; + adjusted_mode->Flags = radeon_output->Flags; + } + if ((radeon_output->MonType == MT_LCD || radeon_output->MonType == MT_DFP) && radeon_output->rmx_type != RMX_OFF) { xf86CrtcPtr crtc = output->crtc; RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; - if ((mode->HDisplay < radeon_output->PanelXRes || - mode->VDisplay < radeon_output->PanelYRes) && - radeon_crtc->crtc_id == 0) + if (radeon_crtc->crtc_id == 0) adjusted_mode->Flags |= RADEON_USE_RMX; if (adjusted_mode->Flags & RADEON_USE_RMX) { radeon_output->Flags |= RADEON_USE_RMX; - if (radeon_output->MonType == MT_DFP) { - adjusted_mode->CrtcHTotal = mode->CrtcHDisplay + radeon_output->HBlank; - adjusted_mode->CrtcHSyncStart = mode->CrtcHDisplay + radeon_output->HOverPlus; - adjusted_mode->CrtcHSyncEnd = mode->CrtcHSyncStart + radeon_output->HSyncWidth; - adjusted_mode->CrtcVTotal = mode->CrtcVDisplay + radeon_output->VBlank; - adjusted_mode->CrtcVSyncStart = mode->CrtcVDisplay + radeon_output->VOverPlus; - adjusted_mode->CrtcVSyncEnd = mode->CrtcVSyncStart + radeon_output->VSyncWidth; - adjusted_mode->Clock = radeon_output->DotClock; - adjusted_mode->Flags = radeon_output->Flags; - } + + adjusted_mode->CrtcHTotal = mode->CrtcHDisplay + radeon_output->HBlank; + adjusted_mode->CrtcHSyncStart = mode->CrtcHDisplay + radeon_output->HOverPlus; + adjusted_mode->CrtcHSyncEnd = mode->CrtcHSyncStart + radeon_output->HSyncWidth; + adjusted_mode->CrtcVTotal = mode->CrtcVDisplay + radeon_output->VBlank; + adjusted_mode->CrtcVSyncStart = mode->CrtcVDisplay + radeon_output->VOverPlus; + adjusted_mode->CrtcVSyncEnd = mode->CrtcVSyncStart + radeon_output->VSyncWidth; + adjusted_mode->Clock = radeon_output->DotClock; + adjusted_mode->Flags = radeon_output->Flags; + } else radeon_output->Flags &= ~RADEON_USE_RMX; |