diff options
Diffstat (limited to 'src/radeon_mergedfb.c')
-rw-r--r-- | src/radeon_mergedfb.c | 77 |
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; |