summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Deucher <alex@t41p.hsd1.va.comcast.net>2007-09-30 12:02:54 -0400
committerAlex Deucher <alex@t41p.hsd1.va.comcast.net>2007-09-30 12:02:54 -0400
commit99ceaefa18c6e07b55106cca0ea8996fa73667be (patch)
tree98e594f98aadd19cf21a62b8f38e055441238bf4
parentd808781d48adf01e80b5bb476bae2d2f599030f1 (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.c103
-rw-r--r--src/radeon_output.c37
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;