summaryrefslogtreecommitdiff
path: root/src/radeon_mergedfb.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/radeon_mergedfb.c')
-rw-r--r--src/radeon_mergedfb.c77
1 files changed, 50 insertions, 27 deletions
diff --git a/src/radeon_mergedfb.c b/src/radeon_mergedfb.c
index 90166772..c4d00c96 100644
--- a/src/radeon_mergedfb.c
+++ b/src/radeon_mergedfb.c
@@ -122,9 +122,9 @@ RADEONStrToRanges(range *r, char *s, int max)
return rangenum;
}
-/* Copy and link two modes form merged-fb mode
+/* Copy and link two modes (i, j) for merged-fb mode
* (Taken from mga, sis drivers)
- * Copys mode i, links the result to dest, and returns it.
+ * Copys mode i, merges j to copy of i, links the result to dest, and returns it.
* Links i and j in Private record.
* If dest is NULL, return value is copy of i linked to itself.
* For mergedfb auto-config, we only check the dimension
@@ -204,16 +204,22 @@ RADEONCopyModeNLink(ScrnInfoPtr pScrn, DisplayModePtr dest,
mode->VSyncStart += dy;
mode->VSyncEnd += dy;
mode->VTotal += dy;
- mode->Clock = 0;
+
+ /* Provide a sophisticated fake DotClock in order to trick the vidmode
+ * extension to allow selecting among a number of modes whose merged result
+ * looks identical but consists of different modes for CRT1 and CRT2
+ */
+ mode->Clock = (((i->Clock >> 3) + i->HTotal) << 16) | ((j->Clock >> 2) + j->HTotal);
+ mode->Clock ^= ((i->VTotal << 19) | (j->VTotal << 3));
if( ((mode->HDisplay * ((pScrn->bitsPerPixel + 7) / 8) * mode->VDisplay) >
(pScrn->videoRam * 1024)) ||
- (mode->HDisplay > 8192) ||
- (mode->VDisplay > 8192) ) {
+ (mode->HDisplay > 8191) ||
+ (mode->VDisplay > 8191) ) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "Skipped %dx%d, not enough video RAM or beyond hardware specs\n",
- mode->HDisplay, mode->VDisplay);
+ "Skipped \"%s\" (%dx%d), not enough video RAM or beyond hardware specs\n",
+ mode->name, mode->HDisplay, mode->VDisplay);
xfree(mode->Private);
xfree(mode);
@@ -225,8 +231,8 @@ RADEONCopyModeNLink(ScrnInfoPtr pScrn, DisplayModePtr dest,
}
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "Merged %dx%d and %dx%d to %dx%d%s\n",
- i->HDisplay, i->VDisplay, j->HDisplay, j->VDisplay,
+ "Merged \"%s\" (%dx%d) and \"%s\" (%dx%d) to %dx%d%s\n",
+ i->name, i->HDisplay, i->VDisplay, j->name, j->HDisplay, j->VDisplay,
mode->HDisplay, mode->VDisplay, (srel == radeonClone) ? " (Clone)" : "");
mode->next = mode;
@@ -243,7 +249,7 @@ RADEONCopyModeNLink(ScrnInfoPtr pScrn, DisplayModePtr dest,
}
/* Helper function to find a mode from a given name
- * (Taken from mga driver)
+ * (Taken from mga, sis drivers)
*/
static DisplayModePtr
RADEONGetModeFromName(char* str, DisplayModePtr i)
@@ -329,7 +335,7 @@ RADEONGenerateModeListFromLargestModes(ScrnInfoPtr pScrn,
}
/* Generate the merged-fb mode modelist
- * (Taken from mga driver)
+ * (Taken from mga, sis drivers)
*/
static DisplayModePtr
RADEONGenerateModeListFromMetaModes(ScrnInfoPtr pScrn, char* str,
@@ -338,11 +344,12 @@ RADEONGenerateModeListFromMetaModes(ScrnInfoPtr pScrn, char* str,
{
char* strmode = str;
char modename[256];
- Bool gotdash = FALSE;
+ Bool gotdash = FALSE, gotplus = FALSE;
RADEONScrn2Rel sr;
DisplayModePtr mode1 = NULL;
DisplayModePtr mode2 = NULL;
DisplayModePtr result = NULL;
+ int myslen;
RADEONInfoPtr info = RADEONPTR(pScrn);
info->AtLeastOneNonClone = FALSE;
@@ -351,21 +358,29 @@ RADEONGenerateModeListFromMetaModes(ScrnInfoPtr pScrn, char* str,
switch(*str) {
case 0:
case '-':
+ case '+':
case ' ':
- if((strmode != str)) {
+ if(strmode != str) {
- strncpy(modename, strmode, str - strmode);
- modename[str - strmode] = 0;
+ myslen = str - strmode;
+ if(myslen > 255) myslen = 255;
+ strncpy(modename, strmode, myslen);
+ modename[myslen] = 0;
if(gotdash) {
- if(mode1 == NULL) return NULL;
+ if(mode1 == NULL) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Error parsing MetaModes parameter\n");
+ return NULL;
+ }
mode2 = RADEONGetModeFromName(modename, j);
if(!mode2) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Mode \"%s\" is not a supported mode for CRT2\n", modename);
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- "Skipping metamode \"%s-%s\".\n", mode1->name, modename);
+ "\t(Skipping metamode \"%s%s%s\")\n", mode1->name, gotplus ? "+" : "-", modename);
mode1 = NULL;
+ gotplus = FALSE;
}
} else {
mode1 = RADEONGetModeFromName(modename, i);
@@ -373,25 +388,31 @@ RADEONGenerateModeListFromMetaModes(ScrnInfoPtr pScrn, char* str,
char* tmps = str;
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Mode \"%s\" is not a supported mode for CRT1\n", modename);
- gotdash = FALSE;
while(*tmps == ' ') tmps++;
- if(*tmps == '-') { /* skip the next mode */
+ /* skip the next mode */
+ if((*tmps == '-') || (*tmps == '+')) {
tmps++;
- while((*tmps == ' ') && (*tmps != 0)) tmps++; /* skip spaces */
- while((*tmps != ' ') && (*tmps != '-') && (*tmps != 0)) tmps++; /* skip modename */
- strncpy(modename,strmode,tmps - strmode);
- modename[tmps - strmode] = 0;
+ /* skip spaces */
+ while(*tmps == ' ') tmps++;
+ /* skip modename */
+ while((*tmps != ' ') && (*tmps != '-') && (*tmps != '+') && (*tmps != 0)) tmps++;
+ myslen = tmps - strmode;
+ if(myslen > 255) myslen = 255;
+ strncpy(modename,strmode,myslen);
+ modename[myslen] = 0;
str = tmps-1;
}
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- "Skipping metamode \"%s\".\n", modename);
+ "\t(Skipping metamode \"%s\")\n", modename);
mode1 = NULL;
+ gotplus = FALSE;
}
}
gotdash = FALSE;
}
strmode = str + 1;
- gotdash |= (*str == '-');
+ gotdash |= ((*str == '-') || (*str == '+'));
+ gotplus |= (*str == '+');
if(*str != 0) break;
/* Fall through otherwise */
@@ -399,21 +420,23 @@ RADEONGenerateModeListFromMetaModes(ScrnInfoPtr pScrn, char* str,
default:
if(!gotdash && mode1) {
sr = srel;
+ if(gotplus) sr = radeonClone;
if(!mode2) {
mode2 = RADEONGetModeFromName(mode1->name, j);
sr = radeonClone;
}
if(!mode2) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- "Mode: \"%s\" is not a supported mode for CRT2\n", mode1->name);
+ "Mode \"%s\" is not a supported mode for CRT2\n", mode1->name);
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- "Skipping metamode \"%s\".\n", mode1->name);
+ "\t(Skipping metamode \"%s\")\n", modename);
mode1 = NULL;
} else {
result = RADEONCopyModeNLink(pScrn, result, mode1, mode2, sr);
mode1 = NULL;
mode2 = NULL;
}
+ gotplus = FALSE;
}
break;