--- ../ati.orig/radeon_cursor.c 2003-04-07 11:29:21.000000000 -0400 +++ ./radeon_cursor.c 2003-05-20 00:29:26.000000000 -0400 @@ -89,6 +89,9 @@ #endif +static void +RADEONSetCursorPositionMerged(ScrnInfoPtr pScrn, int x, int y); + /* Set cursor foreground and background colors */ static void RADEONSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) { @@ -142,6 +145,11 @@ int Y2 = pScrn->frameY0 + y; int stride = 256; + if(info->MergedFB) { + RADEONSetCursorPositionMerged(pScrn, x, y); + return; + } + if (x < 0) xorigin = -x+1; if (y < 0) yorigin = -y+1; if (y > total_y) y = total_y; @@ -149,57 +157,6 @@ if (xorigin >= cursor->MaxWidth) xorigin = cursor->MaxWidth - 1; if (yorigin >= cursor->MaxHeight) yorigin = cursor->MaxHeight - 1; - if (info->Clone) { - int X0 = 0; - int Y0 = 0; - - if ((info->CurCloneMode->VDisplay == pScrn->currentMode->VDisplay) && - (info->CurCloneMode->HDisplay == pScrn->currentMode->HDisplay)) { - Y2 = y; - X2 = x; - X0 = pScrn->frameX0; - Y0 = pScrn->frameY0; - } else { - if (y < 0) - Y2 = pScrn->frameY0; - - if (x < 0) - X2 = pScrn->frameX0; - - if (Y2 >= info->CurCloneMode->VDisplay + info->CloneFrameY0) { - Y0 = Y2 - info->CurCloneMode->VDisplay; - Y2 = info->CurCloneMode->VDisplay - 1; - } else if (Y2 < info->CloneFrameY0) { - Y0 = Y2; - Y2 = 0; - } else { - Y2 -= info->CloneFrameY0; - Y0 = info->CloneFrameY0; - } - - if (X2 >= info->CurCloneMode->HDisplay + info->CloneFrameX0) { - X0 = X2 - info->CurCloneMode->HDisplay; - X2 = info->CurCloneMode->HDisplay - 1; - } else if (X2 < info->CloneFrameX0) { - X0 = X2; - X2 = 0; - } else { - X2 -= info->CloneFrameX0; - X0 = info->CloneFrameX0; - } - - if (info->CurCloneMode->Flags & V_DBLSCAN) - Y2 *= 2; - } - - if ((X0 >= 0 || Y0 >= 0) && - ((info->CloneFrameX0 != X0) || (info->CloneFrameY0 != Y0))) { - RADEONDoAdjustFrame(pScrn, X0, Y0, TRUE); - info->CloneFrameX0 = X0; - info->CloneFrameY0 = Y0; - } - } - if (!info->IsSecondary) { OUTREG(RADEON_CUR_HORZ_VERT_OFF, (RADEON_CUR_LOCK | (xorigin << 16) @@ -219,23 +176,59 @@ info->cursor_start + pScrn->fbOffset + yorigin * stride); } - if (info->Clone) { - xorigin = 0; - yorigin = 0; - if (X2 < 0) xorigin = -X2 + 1; - if (Y2 < 0) yorigin = -Y2 + 1; - if (xorigin >= cursor->MaxWidth) xorigin = cursor->MaxWidth - 1; - if (yorigin >= cursor->MaxHeight) yorigin = cursor->MaxHeight - 1; +} - OUTREG(RADEON_CUR2_HORZ_VERT_OFF, (RADEON_CUR2_LOCK +static void +RADEONSetCursorPositionMerged(ScrnInfoPtr pScrn, int x, int y) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + xf86CursorInfoPtr cursor = info->cursor; + int xorigin = 0; + int yorigin = 0; + int stride = 256; + ScrnInfoPtr pScrn2 = info->CRT2pScrn; + DisplayModePtr mode1 = CDMPTR->CRT1; + DisplayModePtr mode2 = CDMPTR->CRT2; + int x1, y1, x2, y2; + + x += pScrn->frameX0; + y += pScrn->frameY0; + + x1 = x - info->CRT1frameX0; + y1 = y - info->CRT1frameY0; + + x2 = x - pScrn2->frameX0; + y2 = y - pScrn2->frameY0; + + if(mode1->Flags & V_INTERLACE) + y1 /= 2; + else if(mode1->Flags & V_DBLSCAN) + y1 *= 2; + + if(mode2->Flags & V_INTERLACE) + y2 /= 2; + else if(mode2->Flags & V_DBLSCAN) + y2 *= 2; + + /* cursor1 */ + OUTREG(RADEON_CUR_HORZ_VERT_OFF, (RADEON_CUR_LOCK + | (xorigin << 16) + | yorigin)); + OUTREG(RADEON_CUR_HORZ_VERT_POSN, (RADEON_CUR_LOCK + | ((xorigin ? 0 : x1) << 16) + | (yorigin ? 0 : y1))); + OUTREG(RADEON_CUR_OFFSET, info->cursor_start + yorigin * stride); + + /* cursor2 */ + OUTREG(RADEON_CUR2_HORZ_VERT_OFF, (RADEON_CUR2_LOCK | (xorigin << 16) | yorigin)); - OUTREG(RADEON_CUR2_HORZ_VERT_POSN, (RADEON_CUR2_LOCK - | ((xorigin ? 0 : X2) << 16) - | (yorigin ? 0 : Y2))); - OUTREG(RADEON_CUR2_OFFSET, + OUTREG(RADEON_CUR2_HORZ_VERT_POSN, (RADEON_CUR2_LOCK + | ((xorigin ? 0 : x2) << 16) + | (yorigin ? 0 : y2))); + OUTREG(RADEON_CUR2_OFFSET, info->cursor_start + pScrn->fbOffset + yorigin * stride); - } } /* Copy cursor image from `image' to video memory. RADEONSetCursorPosition @@ -259,7 +252,7 @@ OUTREG(RADEON_CRTC_GEN_CNTL, save1 & (CARD32)~RADEON_CRTC_CUR_EN); } - if (info->IsSecondary || info->Clone) { + if (info->IsSecondary || info->MergedFB) { save2 = INREG(RADEON_CRTC2_GEN_CNTL) & ~(CARD32) (3 << 20); save2 |= (CARD32) (2 << 20); OUTREG(RADEON_CRTC2_GEN_CNTL, save2 & (CARD32)~RADEON_CRTC2_CUR_EN); @@ -292,7 +285,7 @@ if (!info->IsSecondary) OUTREG(RADEON_CRTC_GEN_CNTL, save1); - if (info->IsSecondary || info->Clone) + if (info->IsSecondary || info->MergedFB) OUTREG(RADEON_CRTC2_GEN_CNTL, save2); } @@ -303,7 +296,7 @@ RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - if (info->IsSecondary || info->Clone) + if (info->IsSecondary || info->MergedFB) OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~RADEON_CRTC2_CUR_EN); if (!info->IsSecondary) @@ -316,7 +309,7 @@ RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - if (info->IsSecondary || info->Clone) + if (info->IsSecondary || info->MergedFB) OUTREGP(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_CUR_EN, ~RADEON_CRTC2_CUR_EN); @@ -369,7 +362,7 @@ OUTREG(RADEON_CRTC_GEN_CNTL, save1 & (CARD32)~RADEON_CRTC_CUR_EN); } - if (info->IsSecondary || info->Clone) { + if (info->IsSecondary || info->MergedFB) { save2 = INREG(RADEON_CRTC2_GEN_CNTL) & ~(CARD32) (3 << 20); save2 |= (CARD32) (2 << 20); OUTREG(RADEON_CRTC2_GEN_CNTL, save2 & (CARD32)~RADEON_CRTC2_CUR_EN); @@ -407,7 +400,7 @@ if (!info->IsSecondary) OUTREG(RADEON_CRTC_GEN_CNTL, save1); - if (info->IsSecondary || info->Clone) + if (info->IsSecondary || info->MergedFB) OUTREG(RADEON_CRTC2_GEN_CNTL, save2); } --- ../ati.orig/radeon_driver.c 2003-04-23 17:51:31.000000000 -0400 +++ radeon_driver.c 2003-07-13 18:16:47.000000000 -0400 @@ -115,6 +115,8 @@ static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags); +Bool InRegion(int x, int y, region r); +void RADEONMergePointerMoved(int scrnIndex, int x, int y); typedef enum { OPTION_NOACCEL, @@ -139,11 +141,13 @@ OPTION_MONITOR_LAYOUT, OPTION_IGNORE_EDID, OPTION_CRTC2_OVERLAY, - OPTION_CLONE_MODE, - OPTION_CLONE_HSYNC, - OPTION_CLONE_VREFRESH, OPTION_FBDEV, - OPTION_VIDEO_KEY + OPTION_VIDEO_KEY, + OPTION_MERGEDFB, + OPTION_CRT2HSYNC, + OPTION_CRT2VREFRESH, + OPTION_CRT2POS, + OPTION_METAMODES } RADEONOpts; const OptionInfoRec RADEONOptions[] = { @@ -169,11 +173,13 @@ { OPTION_MONITOR_LAYOUT, "MonitorLayout", OPTV_ANYSTR, {0}, FALSE }, { OPTION_IGNORE_EDID, "IgnoreEDID", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_CRTC2_OVERLAY , "OverlayOnCRTC2", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_CLONE_MODE, "CloneMode", OPTV_ANYSTR, {0}, FALSE }, - { OPTION_CLONE_HSYNC, "CloneHSync", OPTV_ANYSTR, {0}, FALSE }, - { OPTION_CLONE_VREFRESH, "CloneVRefresh", OPTV_ANYSTR, {0}, FALSE }, { OPTION_FBDEV, "UseFBDev", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE }, + { OPTION_MERGEDFB, "MergedFB", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_CRT2HSYNC, "CRT2HSync", OPTV_ANYSTR, {0}, FALSE }, + { OPTION_CRT2VREFRESH, "CRT2VRefresh", OPTV_ANYSTR, {0}, FALSE }, + { OPTION_CRT2POS, "CRT2Position", OPTV_ANYSTR, {0}, FALSE }, + { OPTION_METAMODES, "MetaModes", OPTV_ANYSTR, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; @@ -543,6 +549,48 @@ /* Free our private RADEONInfoRec */ static void RADEONFreeRec(ScrnInfoPtr pScrn) { + RADEONInfoPtr info = RADEONPTR(pScrn); + if(info->CRT2HSync) xfree(info->CRT2HSync); + info->CRT2HSync = NULL; + if(info->CRT2VRefresh) xfree(info->CRT2VRefresh); + info->CRT2VRefresh = NULL; + if(info->MetaModes) xfree(info->MetaModes); + info->MetaModes = NULL; + if(info->CRT2pScrn) { + if(info->CRT2pScrn->modes) { + while(info->CRT2pScrn->modes) + xf86DeleteMode(&info->CRT2pScrn->modes, info->CRT2pScrn->modes); + } + if(info->CRT2pScrn->monitor) { + if(info->CRT2pScrn->monitor->Modes) { + while(info->CRT2pScrn->monitor->Modes) + xf86DeleteMode(&info->CRT2pScrn->monitor->Modes, info->CRT2pScrn->monitor->Modes); + } + if(info->CRT2pScrn->monitor->DDC) xfree(info->CRT2pScrn->monitor->DDC); + xfree(info->CRT2pScrn->monitor); + } + xfree(info->CRT2pScrn); + info->CRT2pScrn = NULL; + } + if(info->CRT1Modes) { + if(info->CRT1Modes != pScrn->modes) { + if(pScrn->modes) { + pScrn->currentMode = pScrn->modes; + do { + DisplayModePtr p = pScrn->currentMode->next; + if(pScrn->currentMode->Private) + xfree(pScrn->currentMode->Private); + xfree(pScrn->currentMode); + pScrn->currentMode = p; + } while(pScrn->currentMode != pScrn->modes); + } + pScrn->currentMode = info->CRT1CurrentMode; + pScrn->modes = info->CRT1Modes; + info->CRT1CurrentMode = NULL; + info->CRT1Modes = NULL; + } + } + if (!pScrn || !pScrn->driverPrivate) return; xfree(pScrn->driverPrivate); pScrn->driverPrivate = NULL; @@ -736,7 +784,7 @@ default: break; } - if (info->Clone) + if (info->MergedFB) OUTREGP(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS | @@ -777,7 +825,7 @@ default: break; } - if (info->Clone) + if (info->MergedFB) OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~(RADEON_CRTC2_DISP_DIS | @@ -818,6 +866,481 @@ return (n + (d / 2)) / d; } +/* mergedfb functions */ +/* Helper function for CRT2 monitor vrefresh/hsync options + * (Taken from mga driver) + */ +static int +RADEONStrToRanges(range *r, char *s) +{ + float num = 0.0; + int rangenum = 0; + Bool gotdash = FALSE; + Bool nextdash = FALSE; + char* strnum = NULL; + do { + switch(*s) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '.': + if(strnum == NULL) { + strnum = s; + gotdash = nextdash; + nextdash = FALSE; + } + break; + case '-': + case ' ': + case 0: + if(strnum == NULL) break; + if(strnum != NULL) sscanf(strnum,"%f",&num); + if(gotdash) + r[rangenum - 1].hi = num; + else { + r[rangenum].lo = num; + r[rangenum].hi = num; + rangenum++; + } + strnum = NULL; + if(*s == '-') nextdash = (rangenum != 0); + break; + default : + return 0; + } + } while(*(s++) != 0); + + return rangenum; +} + +/* Copy and link two modes form merged-fb mode + * (Taken from mga driver) + * Copys mode 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. + */ +static DisplayModePtr +RADEONCopyModeNLink(ScrnInfoPtr pScrn, DisplayModePtr dest, + DisplayModePtr i, DisplayModePtr j, + RADEONScrn2Rel srel) +{ + DisplayModePtr mode; + int dx = 0,dy = 0; + + mode = xalloc(sizeof(DisplayModeRec)); + memcpy(mode, i, sizeof(DisplayModeRec)); + mode->Private = xalloc(sizeof(RADEONMergedDisplayModeRec)); + ((RADEONMergedDisplayModePtr)mode->Private)->CRT1 = i; + ((RADEONMergedDisplayModePtr)mode->Private)->CRT2 = j; + ((RADEONMergedDisplayModePtr)mode->Private)->CRT2Position = srel; + mode->PrivSize = 0; + + switch(srel) { + case radeonLeftOf: + case radeonRightOf: + dx = min(pScrn->virtualX, i->HDisplay + j->HDisplay) - mode->HDisplay; + dy = min(pScrn->virtualY, max(i->VDisplay,j->VDisplay)) - mode->VDisplay; + break; + case radeonAbove: + case radeonBelow: + dy = min(pScrn->virtualY, i->VDisplay + j->VDisplay) - mode->VDisplay; + dx = min(pScrn->virtualX, max(i->HDisplay,j->HDisplay)) - mode->HDisplay; + break; + case radeonClone: + dx = min(pScrn->virtualX, max(i->HDisplay,j->HDisplay)) - mode->HDisplay; + dy = min(pScrn->virtualY, max(i->VDisplay,j->VDisplay)) - mode->VDisplay; + break; + } + mode->HDisplay += dx; + mode->HSyncStart += dx; + mode->HSyncEnd += dx; + mode->HTotal += dx; + mode->VDisplay += dy; + mode->VSyncStart += dy; + mode->VSyncEnd += dy; + mode->VTotal += dy; + mode->Clock = 0; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Merged %dx%d and %dx%d to %dx%d (Virtual %d %d)\n", + i->HDisplay, i->VDisplay, j->HDisplay, j->VDisplay, + mode->HDisplay, mode->VDisplay, + pScrn->virtualX, pScrn->virtualY); + + mode->next = mode; + mode->prev = mode; + + if(dest) { + mode->next = dest->next; /* Insert node after "dest" */ + dest->next->prev = mode; + mode->prev = dest; + dest->next = mode; + } + + return mode; +} + +/* Helper function to find a mode from a given name + * (Taken from mga driver) + */ +static DisplayModePtr +RADEONGetModeFromName(char* str, DisplayModePtr i) +{ + DisplayModePtr c = i; + if(!i) return NULL; + do { + if(strcmp(str, c->name) == 0) return c; + c = c->next; + } while(c != i); + return NULL; +} + +/* Generate the merged-fb mode modelist + * (Taken from mga driver) + */ +static DisplayModePtr +RADEONGenerateModeList(ScrnInfoPtr pScrn, char* str, + DisplayModePtr i, DisplayModePtr j, + RADEONScrn2Rel srel) +{ + char* strmode = str; + char modename[256]; + Bool gotdash = FALSE; + RADEONScrn2Rel sr; + DisplayModePtr tempmode; + DisplayModePtr mode1 = NULL; + DisplayModePtr mode2 = NULL; + DisplayModePtr result = NULL; + + /* default case if no metamodes specified */ + if (str == NULL) { + sr = radeonClone; + for (tempmode = i; tempmode->next != i; tempmode = tempmode->next) { + mode1 = RADEONGetModeFromName(tempmode->name, i); + mode2 = RADEONGetModeFromName(mode1->name, j); + if (!mode2) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Mode: \"%s\" is not a supported mode for CRT2\n", mode1->name); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Skipping metamode \"%s\".\n"); + mode1 = NULL; + } else { + result = RADEONCopyModeNLink(pScrn, result, mode1, mode2, sr); + mode1 = NULL; + mode2 = NULL; + } + } + return result; + } + + do { + switch(*str) { + case 0: + case '-': + case ' ': + if((strmode != str)) { + + strncpy(modename, strmode, str - strmode); + modename[str - strmode] = 0; + + if(gotdash) { + if(mode1 == NULL) 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); + mode1 = NULL; + } + } else { + mode1 = RADEONGetModeFromName(modename, i); + if(!mode1) { + 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 */ + 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; + str = tmps-1; + } + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Skipping metamode \"%s\".\n", modename); + mode1 = NULL; + } + } + gotdash = FALSE; + } + strmode = str + 1; + gotdash |= (*str == '-'); + + if(*str != 0) break; + /* Fall through otherwise */ + + default: + if(!gotdash && mode1) { + sr = srel; + 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); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Skipping metamode \"%s\".\n"); + mode1 = NULL; + } else { + result = RADEONCopyModeNLink(pScrn, result, mode1, mode2, sr); + mode1 = NULL; + mode2 = NULL; + } + } + break; + + } + + } while(*(str++) != 0); + + return result; +} + +Bool +InRegion(int x, int y, region r) +{ + return (r.x0 <= x) && (x <= r.x1) && (r.y0 <= y) && (y <= r.y1); +} + +void +RADEONMergePointerMoved(int scrnIndex, int x, int y) +{ + ScrnInfoPtr pScrn1 = xf86Screens[scrnIndex]; + RADEONInfoPtr info = RADEONPTR(pScrn1); + ScrnInfoPtr pScrn2 = info->CRT2pScrn; + region out, in1, in2, f2, f1; + int deltax, deltay; + + f1.x0 = info->CRT1frameX0; + f1.x1 = info->CRT1frameX1; + f1.y0 = info->CRT1frameY0; + f1.y1 = info->CRT1frameY1; + f2.x0 = pScrn2->frameX0; + f2.x1 = pScrn2->frameX1; + f2.y0 = pScrn2->frameY0; + f2.y1 = pScrn2->frameY1; + + /* Define the outer region. Crossing this causes all frames to move */ + out.x0 = pScrn1->frameX0; + out.x1 = pScrn1->frameX1; + out.y0 = pScrn1->frameY0; + out.y1 = pScrn1->frameY1; + + /* + * Define the inner sliding window. Being outsize both frames but + * inside the outer clipping window will slide corresponding frame + */ + in1 = out; + in2 = out; + switch(((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT2Position) { + case radeonLeftOf: + in1.x0 = f1.x0; + in2.x1 = f2.x1; + break; + case radeonRightOf: + in1.x1 = f1.x1; + in2.x0 = f2.x0; + break; + case radeonBelow: + in1.y1 = f1.y1; + in2.y0 = f2.y0; + break; + case radeonAbove: + in1.y0 = f1.y0; + in2.y1 = f2.y1; + break; + case radeonClone: + break; + } + + deltay = 0; + deltax = 0; + + if(InRegion(x, y, out)) { /* inside outer region */ + + /* xf86DrvMsg(0, X_INFO, "1: %d %d | %d %d %d %d | %d %d %d %d\n", + x, y, in1.x0, in1.x1, in1.y0, in1.y1, f1.x0, f1.x1, f1.y0, f1.y1); */ + + if(InRegion(x, y, in1) && !InRegion(x, y, f1)) { + REBOUND(f1.x0, f1.x1, x); + REBOUND(f1.y0, f1.y1, y); + deltax = 1; + /* xf86DrvMsg(0, X_INFO, "2: %d %d | %d %d %d %d | %d %d %d %d\n", + x, y, in1.x0, in1.x1, in1.y0, in1.y1, f1.x0, f1.x1, f1.y0, f1.y1); */ + } + if(InRegion(x, y, in2) && !InRegion(x, y, f2)) { + REBOUND(f2.x0, f2.x1, x); + REBOUND(f2.y0, f2.y1, y); + deltax = 1; + } + + } else { /* outside outer region */ + + /* xf86DrvMsg(0, X_INFO, "3: %d %d | %d %d %d %d | %d %d %d %d\n", + x, y, in1.x0, in1.x1, in1.y0, in1.y1, f1.x0, f1.x1, f1.y0, f1.y1); + xf86DrvMsg(0, X_INFO, "3-out: %d %d %d %d\n", + out.x0, out.x1, out.y0, out.y1); */ + + if(out.x0 > x) { + deltax = x - out.x0; + } + if(out.x1 < x) { + deltax = x - out.x1; + } + if(deltax) { + pScrn1->frameX0 += deltax; + pScrn1->frameX1 += deltax; + f1.x0 += deltax; + f1.x1 += deltax; + f2.x0 += deltax; + f2.x1 += deltax; + } + + if(out.y0 > y) { + deltay = y - out.y0; + } + if(out.y1 < y) { + deltay = y - out.y1; + } + if(deltay) { + pScrn1->frameY0 += deltay; + pScrn1->frameY1 += deltay; + f1.y0 += deltay; + f1.y1 += deltay; + f2.y0 += deltay; + f2.y1 += deltay; + } + + switch(((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT2Position) { + case radeonLeftOf: + if(x >= f1.x0) { REBOUND(f1.y0, f1.y1, y); } + if(x <= f2.x1) { REBOUND(f2.y0, f2.y1, y); } + break; + case radeonRightOf: + if(x <= f1.x1) { REBOUND(f1.y0, f1.y1, y); } + if(x >= f2.x0) { REBOUND(f2.y0, f2.y1, y); } + break; + case radeonBelow: + if(y <= f1.y1) { REBOUND(f1.x0, f1.x1, x); } + if(y >= f2.y0) { REBOUND(f2.x0, f2.x1, x); } + break; + case radeonAbove: + if(y >= f1.y0) { REBOUND(f1.x0, f1.x1, x); } + if(y <= f2.y1) { REBOUND(f2.x0, f2.x1, x); } + break; + case radeonClone: + break; + } + + } + + if(deltax || deltay) { + info->CRT1frameX0 = f1.x0; + info->CRT1frameY0 = f1.y0; + pScrn2->frameX0 = f2.x0; + pScrn2->frameY0 = f2.y0; + + info->CRT1frameX1 = info->CRT1frameX0 + CDMPTR->CRT1->HDisplay - 1; + info->CRT1frameY1 = info->CRT1frameY0 + CDMPTR->CRT1->VDisplay - 1; + pScrn2->frameX1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay - 1; + pScrn2->frameY1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay - 1; + pScrn1->frameX1 = pScrn1->frameX0 + info->CurrentLayout.mode->HDisplay - 1; + pScrn1->frameY1 = pScrn1->frameY0 + info->CurrentLayout.mode->VDisplay - 1; + + RADEONDoAdjustFrame(pScrn1, info->CRT1frameX0, info->CRT1frameY0, FALSE); + RADEONDoAdjustFrame(pScrn1, pScrn2->frameX0, pScrn2->frameY0, TRUE); + } +} + +static void +RADEONAdjustFrameMerged(int scrnIndex, int x, int y, int flags) +{ + ScrnInfoPtr pScrn1 = xf86Screens[scrnIndex]; + RADEONInfoPtr info = RADEONPTR(pScrn1); + ScrnInfoPtr pScrn2 = info->CRT2pScrn; + int VTotal = info->CurrentLayout.mode->VDisplay; + int HTotal = info->CurrentLayout.mode->HDisplay; + int VMax = VTotal; + int HMax = HTotal; + + BOUND(x, 0, pScrn1->virtualX - HTotal); + BOUND(y, 0, pScrn1->virtualY - VTotal); + + switch(SDMPTR(pScrn1)->CRT2Position) { + case radeonLeftOf: + pScrn2->frameX0 = x; + BOUND(pScrn2->frameY0, y, y + VMax - CDMPTR->CRT2->VDisplay); + info->CRT1frameX0 = x + CDMPTR->CRT2->HDisplay; + BOUND(info->CRT1frameY0, y, y + VMax - CDMPTR->CRT1->VDisplay); + break; + case radeonRightOf: + info->CRT1frameX0 = x; + BOUND(info->CRT1frameY0, y, y + VMax - CDMPTR->CRT1->VDisplay); + pScrn2->frameX0 = x + CDMPTR->CRT1->HDisplay; + BOUND(pScrn2->frameY0, y, y + VMax - CDMPTR->CRT2->VDisplay); + break; + case radeonAbove: + BOUND(pScrn2->frameX0, x, x + HMax - CDMPTR->CRT2->HDisplay); + pScrn2->frameY0 = y; + BOUND(info->CRT1frameX0, x, x + HMax - CDMPTR->CRT1->HDisplay); + info->CRT1frameY0 = y + CDMPTR->CRT2->VDisplay; + break; + case radeonBelow: + BOUND(info->CRT1frameX0, x, x + HMax - CDMPTR->CRT1->HDisplay); + info->CRT1frameY0 = y; + BOUND(pScrn2->frameX0, x, x + HMax - CDMPTR->CRT2->HDisplay); + pScrn2->frameY0 = y + CDMPTR->CRT1->VDisplay; + break; + case radeonClone: + BOUND(info->CRT1frameX0, x, x + HMax - CDMPTR->CRT1->HDisplay); + BOUND(info->CRT1frameY0, y, y + VMax - CDMPTR->CRT1->VDisplay); + BOUND(pScrn2->frameX0, x, x + HMax - CDMPTR->CRT2->HDisplay); + BOUND(pScrn2->frameY0, y, y + VMax - CDMPTR->CRT2->VDisplay); + break; + } + + BOUND(info->CRT1frameX0, 0, pScrn1->virtualX - CDMPTR->CRT1->HDisplay); + BOUND(info->CRT1frameY0, 0, pScrn1->virtualY - CDMPTR->CRT1->VDisplay); + BOUND(pScrn2->frameX0, 0, pScrn1->virtualX - CDMPTR->CRT2->HDisplay); + BOUND(pScrn2->frameY0, 0, pScrn1->virtualY - CDMPTR->CRT2->VDisplay); + + pScrn1->frameX0 = x; + pScrn1->frameY0 = y; + + info->CRT1frameX1 = info->CRT1frameX0 + CDMPTR->CRT1->HDisplay - 1; + info->CRT1frameY1 = info->CRT1frameY0 + CDMPTR->CRT1->VDisplay - 1; + pScrn2->frameX1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay - 1; + pScrn2->frameY1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay - 1; + pScrn1->frameX1 = pScrn1->frameX0 + info->CurrentLayout.mode->HDisplay - 1; + pScrn1->frameY1 = pScrn1->frameY0 + info->CurrentLayout.mode->VDisplay - 1; + + RADEONDoAdjustFrame(pScrn1, info->CRT1frameX0, info->CRT1frameY0, FALSE); + RADEONDoAdjustFrame(pScrn1, pScrn2->frameX0, pScrn2->frameY0, TRUE); +} + +/* End of MergedFB helpers */ + static RADEONMonitorType RADEONDisplayDDCConnected(ScrnInfoPtr pScrn, RADEONDDCType DDCType, xf86MonPtr* MonInfo) { RADEONInfoPtr info = RADEONPTR(pScrn); @@ -1485,8 +2008,8 @@ RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); RADEONMMIO = info->MMIO; - info->Clone = FALSE; - info->CloneType = MT_NONE; + info->MergedFB = FALSE; + info->MergeType = MT_NONE; if(info->HasCRTC2) { if(info->IsSecondary) { @@ -1495,8 +2018,8 @@ info->DisplayType = pRADEONEnt->MonType1; if(!pRADEONEnt->HasSecondary) { - if ((info->CloneType = pRADEONEnt->MonType2)) - info->Clone = TRUE; + if ((info->MergeType = pRADEONEnt->MonType2)) + info->MergedFB = TRUE; } } } else { @@ -1507,9 +2030,9 @@ (info->IsSecondary ? "Secondary" : "Primary"), info->DisplayType); - if (info->Clone) - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clone Display == Type %d\n", - info->CloneType); + if (info->MergedFB) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MergedFB Display == Type %d\n", + info->MergeType); info->HBlank = 0; info->HOverPlus = 0; @@ -2106,8 +2629,7 @@ info1 = RADEONPTR(pRADEONEnt->pPrimaryScrn); info1->FbMapSize = pScrn->videoRam * 1024; info->LinearAddr += pScrn->videoRam * 1024; - info1->Clone = FALSE; - info1->CurCloneMode = NULL; + info1->MergedFB = FALSE; } info->R300CGWorkaround = @@ -2976,12 +3498,12 @@ } } -static int RADEONValidateCloneModes(ScrnInfoPtr pScrn) +static int RADEONValidateMergeModes(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); ClockRangePtr clockRanges; DisplayModePtr tmp_mode = NULL; - DisplayModePtr clone_mode, save_mode; + DisplayModePtr merge_mode, save_mode; int modesFound = 0; int count = 0; int tmp_hdisplay = 0; @@ -2989,11 +3511,11 @@ int i, save_n_hsync, save_n_vrefresh; range save_hsync, save_vrefresh; char *s; - char **clone_mode_names = NULL; + char **merge_mode_names = NULL; Bool ddc_mode = info->ddc_mode; RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - /* Save all infomations that will be changed by clone mode validateion */ + /* Save all infomation that will be changed by clone/MergedFB mode validation */ save_mode = pScrn->modes; pScrn->modes = NULL; @@ -3001,13 +3523,13 @@ * head. Allocate one more, in case pScrn->display->modes[0] == * NULL */ while (pScrn->display->modes[count]) count++; - clone_mode_names = xnfalloc((count+2) * sizeof(char*)); + merge_mode_names = xnfalloc((count+2) * sizeof(char*)); for (i = 0; i < count; i++) { - clone_mode_names[i] = xnfalloc(strlen(pScrn->display->modes[i]) + 1); - strcpy(clone_mode_names[i], pScrn->display->modes[i]); + merge_mode_names[i] = xnfalloc(strlen(pScrn->display->modes[i]) + 1); + strcpy(merge_mode_names[i], pScrn->display->modes[i]); } - clone_mode_names[count] = NULL; - clone_mode_names[count+1] = NULL; + merge_mode_names[count] = NULL; + merge_mode_names[count+1] = NULL; pScrn->progClock = TRUE; @@ -3016,24 +3538,11 @@ clockRanges->minClock = info->pll.min_pll_freq; clockRanges->maxClock = info->pll.max_pll_freq * 10; clockRanges->clockIndex = -1; - clockRanges->interlaceAllowed = (info->CloneType == MT_CRT); - clockRanges->doubleScanAllowed = (info->CloneType == MT_CRT); - - /* Only take one clone mode from config file for now, rest of clone - * modes will copy from primary head. - */ - if ((s = xf86GetOptValString(info->Options, OPTION_CLONE_MODE))) { - if (sscanf(s, "%dx%d", &tmp_hdisplay, &tmp_vdisplay) == 2) { - if(count > 0) free(clone_mode_names[0]); - else count++; - clone_mode_names[0] = xnfalloc(strlen(s)+1); - sprintf(clone_mode_names[0], "%dx%d", tmp_hdisplay, tmp_vdisplay); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clone mode %s in config file is used\n"); - } - } + clockRanges->interlaceAllowed = (info->MergeType == MT_CRT); + clockRanges->doubleScanAllowed = (info->MergeType == MT_CRT); for (i = 0; i < count; i++) { - if (sscanf(clone_mode_names[i], "%dx%d", + if (sscanf(merge_mode_names[i], "%dx%d", &tmp_hdisplay, &tmp_vdisplay) == 2) { if (pScrn->display->virtualX < tmp_hdisplay) pScrn->display->virtualX = tmp_hdisplay; @@ -3051,28 +3560,30 @@ pScrn->monitor->nHsync = 0; pScrn->monitor->nVrefresh = 0; - if ((s = xf86GetOptValString(info->Options, OPTION_CLONE_HSYNC))) { + if ((s = xf86GetOptValString(info->Options, OPTION_CRT2HSYNC))) { if (sscanf(s, "%f-%f", &pScrn->monitor->hsync[0].lo, &pScrn->monitor->hsync[0].hi) == 2) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "HSync for CloneMode from config file: %s\n", s); + "HSync for MergedFB Mode from config file: %s\n", s); pScrn->monitor->nHsync = 1; } else { pScrn->monitor->nHsync = 0; } } - if ((s = xf86GetOptValString(info->Options, OPTION_CLONE_VREFRESH))) { + if ((s = xf86GetOptValString(info->Options, OPTION_CRT2VREFRESH))) { if (sscanf(s, "%f-%f", &pScrn->monitor->vrefresh[0].lo, &pScrn->monitor->vrefresh[0].hi) == 2) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "VRefresh for CloneMode from config file: %s\n", s); + "VRefresh for MergedFB Mode from config file: %s\n", s); pScrn->monitor->nVrefresh = 1; } else { pScrn->monitor->nVrefresh = 0; } } + /* copy DDC to CRT2pScrn for setting DPI later */ + info->CRT2pScrn->monitor->DDC = pRADEONEnt->MonInfo2; pScrn->monitor->DDC = pRADEONEnt->MonInfo2; if (pScrn->monitor->DDC) { if ((pScrn->monitor->nVrefresh == 0) || (pScrn->monitor->nHsync == 0)) { @@ -3084,14 +3595,14 @@ } else if (info->ddc_mode) { ddc_mode = FALSE; xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "No DDC data available for clone mode, " + "No DDC data available for MergedFB mode, " "DDCMode option is dismissed\n"); } - if (info->CloneType == MT_CRT && !ddc_mode) { + if (info->MergeType == MT_CRT && !ddc_mode) { modesFound = xf86ValidateModes(pScrn, pScrn->monitor->Modes, - clone_mode_names, + merge_mode_names, clockRanges, NULL, /* linePitches */ 8 * 64, /* minPitch */ @@ -3106,14 +3617,14 @@ } else { /* Try to add DDC modes */ info->IsSecondary = TRUE; /*fake secondary head*/ - modesFound = RADEONValidateDDCModes(pScrn, clone_mode_names, - info->CloneType); + modesFound = RADEONValidateDDCModes(pScrn, merge_mode_names, + info->MergeType); info->IsSecondary = FALSE; /* If that fails and we're connect to a flat panel, then try to * add the flat panel modes */ - if (modesFound < 1 && info->CloneType != MT_CRT) { + if (modesFound < 1 && info->MergeType != MT_CRT) { /* when panel size is not valid, try to validate * mode using xf86ValidateModes routine * This can happen when DDC is disabled. @@ -3121,7 +3632,7 @@ if (info->PanelXRes < 320 || info->PanelYRes < 200) modesFound = xf86ValidateModes(pScrn, pScrn->monitor->Modes, - clone_mode_names, + merge_mode_names, clockRanges, NULL, /* linePitches */ 8 * 64, /* minPitch */ @@ -3134,44 +3645,58 @@ info->FbMapSize, LOOKUP_BEST_REFRESH); else - modesFound = RADEONValidateFPModes(pScrn, clone_mode_names); + modesFound = RADEONValidateFPModes(pScrn, merge_mode_names); } } + /* copy modes to CRT2pScrn */ + info->CRT2pScrn->modes = pScrn->modes; + /* probably need mm for DPI later */ + info->CRT2pScrn->monitor->widthmm = pScrn->monitor->widthmm; + info->CRT2pScrn->monitor->heightmm = pScrn->monitor->heightmm; + info->CRT2pScrn->monitor->hsync[0] = pScrn->monitor->hsync[0]; + info->CRT2pScrn->monitor->vrefresh[0] = pScrn->monitor->vrefresh[0]; + info->CRT2pScrn->monitor->nHsync = pScrn->monitor->nHsync; + info->CRT2pScrn->monitor->nVrefresh = pScrn->monitor->nVrefresh; + info->CRT2pScrn->display->virtualX = pScrn->display->virtualX; + info->CRT2pScrn->display->virtualY = pScrn->display->virtualY; + info->CRT2pScrn->virtualX = pScrn->virtualX; + info->CRT2pScrn->virtualY = pScrn->virtualY; + RADEONSetPitch(info->CRT2pScrn); + if (modesFound > 0) { int valid = 0; - save_mode = pScrn->modes; - xf86SetCrtcForModes(pScrn, 0); - xf86PrintModes(pScrn); + xf86SetCrtcForModes(info->CRT2pScrn, INTERLACE_HALVE_V); /* 0); */ + xf86PrintModes(info->CRT2pScrn); for (i = 0; i < modesFound; i++) { - while (pScrn->modes->status != MODE_OK) { - pScrn->modes = pScrn->modes->next; + while (info->CRT2pScrn->modes->status != MODE_OK) { + info->CRT2pScrn->modes = info->CRT2pScrn->modes->next; } - if (!pScrn->modes) break; + if (!info->CRT2pScrn->modes) break; - if (pScrn->modes->Clock != 0.0) { + if (info->CRT2pScrn->modes->Clock != 0.0) { - clone_mode = xnfcalloc (1, sizeof (DisplayModeRec)); - if (!clone_mode) break; - memcpy(clone_mode, pScrn->modes, sizeof(DisplayModeRec)); - clone_mode->name = xnfalloc(strlen(pScrn->modes->name) + 1); - strcpy(clone_mode->name, pScrn->modes->name); - - if (!info->CurCloneMode) { - info->CloneModes = clone_mode; - info->CurCloneMode = clone_mode; - clone_mode->prev = NULL; + merge_mode = xnfcalloc (1, sizeof (DisplayModeRec)); + if (!merge_mode) break; + memcpy(merge_mode, info->CRT2pScrn->modes, sizeof(DisplayModeRec)); + merge_mode->name = xnfalloc(strlen(info->CRT2pScrn->modes->name) + 1); + strcpy(merge_mode->name, info->CRT2pScrn->modes->name); + + if (!info->CRT2pScrn->modes) { + info->CRT2pScrn->modes = merge_mode; + info->CRT2pScrn->currentMode = merge_mode; + merge_mode->prev = NULL; } else { - clone_mode->prev = tmp_mode; - clone_mode->prev->next = clone_mode; + merge_mode->prev = tmp_mode; + merge_mode->prev->next = merge_mode; } valid++; - tmp_mode = clone_mode; - clone_mode->next = NULL; + tmp_mode = merge_mode; + merge_mode->next = NULL; } - pScrn->modes = pScrn->modes->next; + info->CRT2pScrn->modes = info->CRT2pScrn->modes->next; } /* no longer needed, free it */ @@ -3189,14 +3714,14 @@ } /* Clone_mode_names list is no longer needed, free it. */ - if (clone_mode_names) { - for (i = 0; clone_mode_names[i]; i++) { - free(clone_mode_names[i]); - clone_mode_names[i] = NULL; + if (merge_mode_names) { + for (i = 0; merge_mode_names[i]; i++) { + free(merge_mode_names[i]); + merge_mode_names[i] = NULL; } - free(clone_mode_names); - clone_mode_names = NULL; + free(merge_mode_names); + merge_mode_names = NULL; } /* We need to restore all changed info for the primary head */ @@ -3205,6 +3730,7 @@ pScrn->monitor->vrefresh[0] = save_vrefresh; pScrn->monitor->nHsync = save_n_hsync; pScrn->monitor->nVrefresh = save_n_vrefresh; + pScrn->monitor->DDC = pRADEONEnt->MonInfo1; /* * Also delete the clockRanges (if it was setup) since it will be @@ -3280,24 +3806,23 @@ * DRI. */ if (info->HasCRTC2) { - if (info->Clone) { + if (info->MergedFB) { /* If we have 2 screens from the config file, we don't need * to do clone thing, let each screen handles one head. */ if (!pRADEONEnt->HasSecondary) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Clone modes validation ------------ \n"); + "MergedFB modes validation ------------ \n"); - modesFound = RADEONValidateCloneModes(pScrn); + modesFound = RADEONValidateMergeModes(pScrn); if (modesFound < 1) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "No valid mode found for CRTC2 clone\n"); - info->Clone = FALSE; - info->CurCloneMode = NULL; + "No valid mode found for CRTC2 \n"); + info->MergedFB = FALSE; } xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Total of %d clone modes found ------------ \n\n", + "Total of %d MergedFB modes found ------------ \n\n", modesFound); } } @@ -3461,31 +3986,73 @@ xf86SetCrtcForModes(pScrn, 0); - /* We need to adjust virtual size if the clone modes have larger - * display size. - */ - if (info->Clone && info->CloneModes) { - DisplayModePtr clone_mode = info->CloneModes; - while (1) { - if ((clone_mode->HDisplay > pScrn->virtualX) || - (clone_mode->VDisplay > pScrn->virtualY)) { - pScrn->virtualX = - pScrn->display->virtualX = clone_mode->HDisplay; - pScrn->virtualY = - pScrn->display->virtualY = clone_mode->VDisplay; - RADEONSetPitch(pScrn); - } - if (!clone_mode->next) break; - clone_mode = clone_mode->next; - } - } - pScrn->currentMode = pScrn->modes; + if(info->MergedFB) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Modes for CRT1: ********************\n"); + } xf86PrintModes(pScrn); + if(info->MergedFB) { + + /* xf86SetCrtcForModes(info->CRT2pScrn, INTERLACE_HALVE_V); */ + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Modes for CRT2: ********************\n"); + + xf86PrintModes(info->CRT2pScrn); + + info->CRT1Modes = pScrn->modes; + info->CRT1CurrentMode = pScrn->currentMode; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Generating MergedFB mode list\n"); + + pScrn->modes = RADEONGenerateModeList(pScrn, info->MetaModes, + info->CRT1Modes, info->CRT2pScrn->modes, + info->CRT2Position); + + if(!pScrn->modes) { + + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to parse MetaModes or no modes found. MergeFB mode disabled.\n"); + if(info->CRT2pScrn) { + if(info->CRT2pScrn->modes) { + while(info->CRT2pScrn->modes) + xf86DeleteMode(&info->CRT2pScrn->modes, info->CRT2pScrn->modes); + } + if(info->CRT2pScrn->monitor) { + if(info->CRT2pScrn->monitor->Modes) { + while(info->CRT2pScrn->monitor->Modes) + xf86DeleteMode(&info->CRT2pScrn->monitor->Modes, info->CRT2pScrn->monitor->Modes); + } + if(info->CRT2pScrn->monitor->DDC) xfree(info->CRT2pScrn->monitor->DDC); + xfree(info->CRT2pScrn->monitor); + } + xfree(info->CRT2pScrn); + } + pScrn->modes = info->CRT1Modes; + info->CRT1Modes = NULL; + info->MergedFB = FALSE; + + } else { + + pScrn->modes = pScrn->modes->next; + pScrn->currentMode = pScrn->modes; +#if 0 + /* TW: Update CurrentLayout */ + info->CurrentLayout.mode = pScrn->currentMode; + info->CurrentLayout.displayWidth = pScrn->displayWidth; +#endif + } + } + /* Set DPI */ xf86SetDpi(pScrn, 0, 0); - +#if 1 + if(info->MergedFB) { + xf86SetDpi(info->CRT2pScrn, 0, 0); + } +#endif /* Get ScreenInit function */ #ifdef USE_FB mod = "fb"; @@ -3725,6 +4292,7 @@ RADEONInfoPtr info; xf86Int10InfoPtr pInt10 = NULL; void *int10_save = NULL; + char *strptr; RADEONTRACE(("RADEONPreInit\n")); if (pScrn->numEntities != 1) return FALSE; @@ -3733,9 +4301,7 @@ info = RADEONPTR(pScrn); info->IsSecondary = FALSE; - info->Clone = FALSE; - info->CurCloneMode = NULL; - info->CloneModes = NULL; + info->MergedFB = FALSE; info->IsSwitching = FALSE; info->pEnt = xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]); @@ -3857,6 +4423,89 @@ } } + /* collect MergedFB options */ + info->MergedFB = TRUE; + info->CRT2Position = radeonClone; + xf86GetOptValBool(info->Options, OPTION_MERGEDFB,&(info->MergedFB)); + + /* TW: Do some MergedFB mode initialisation */ + if(info->MergedFB) { + info->CRT2pScrn = xalloc(sizeof(ScrnInfoRec)); + if(!info->CRT2pScrn) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to allocate memory for merged pScrn, MergedFB mode is disabled\n"); + info->MergedFB = FALSE; + } else { + memcpy(info->CRT2pScrn, pScrn, sizeof(ScrnInfoRec)); + } + } + if(info->MergedFB) { + strptr = (char *)xf86GetOptValString(info->Options, OPTION_CRT2POS); + if(strptr) { + if((!strcmp(strptr,"LeftOf")) || (!strcmp(strptr,"leftof"))) + info->CRT2Position = radeonLeftOf; + else if((!strcmp(strptr,"RightOf")) || (!strcmp(strptr,"rightof"))) + info->CRT2Position = radeonRightOf; + else if((!strcmp(strptr,"Above")) || (!strcmp(strptr,"above"))) + info->CRT2Position = radeonAbove; + else if((!strcmp(strptr,"Below")) || (!strcmp(strptr,"below"))) + info->CRT2Position = radeonBelow; + else if((!strcmp(strptr,"Clone")) || (!strcmp(strptr,"clone"))) + info->CRT2Position = radeonClone; + else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "\"%s\" is not a valid parameter for Option \"CRT2Position\"\n", strptr); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Valid parameters are \"RightOf\", \"LeftOf\", \"Above\", \"Below\", or \"Clone\"\n"); + } + } + strptr = (char *)xf86GetOptValString(info->Options, OPTION_METAMODES); + if(strptr) { + info->MetaModes = xalloc(strlen(strptr) + 1); + if(info->MetaModes) memcpy(info->MetaModes, strptr, strlen(strptr) + 1); + } + if(info->MetaModes) { + strptr = (char *)xf86GetOptValString(info->Options, OPTION_CRT2HSYNC); + if(strptr) { + info->CRT2HSync = xalloc(strlen(strptr) + 1); + if(info->CRT2HSync) memcpy(info->CRT2HSync, strptr, strlen(strptr) + 1); + } + strptr = (char *)xf86GetOptValString(info->Options, OPTION_CRT2VREFRESH); + if(strptr) { + info->CRT2VRefresh = xalloc(strlen(strptr) + 1); + if(info->CRT2VRefresh) memcpy(info->CRT2VRefresh, strptr, strlen(strptr) + 1); + } + } else if (info->CRT2Position != radeonClone) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Option \"MergedFB\" requires Option \"MetaModes\".\n"); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "MergedFB mode disabled.\n"); + info->MergedFB = FALSE; + } + } + + if(info->MergedFB) { + info->CRT2pScrn->monitor = xalloc(sizeof(MonRec)); + if(info->CRT2pScrn->monitor) { + memcpy(info->CRT2pScrn->monitor, pScrn->monitor, sizeof(MonRec)); + info->CRT2pScrn->monitor->DDC = NULL; + info->CRT2pScrn->monitor->Modes = NULL; + if(info->CRT2HSync) { + info->CRT2pScrn->monitor->nHsync = + RADEONStrToRanges(info->CRT2pScrn->monitor->hsync, info->CRT2HSync); + } + if(info->CRT2VRefresh) { + info->CRT2pScrn->monitor->nVrefresh = + RADEONStrToRanges(info->CRT2pScrn->monitor->vrefresh, info->CRT2VRefresh); + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to allocate memory for CRT2 monitor, MergedFB mode disabled.\n"); + if(info->CRT2pScrn) xfree(info->CRT2pScrn); + info->CRT2pScrn = NULL; + info->MergedFB = FALSE; + } + } + if (!info->FBDev) if (!RADEONPreInitInt10(pScrn, &pInt10)) goto fail; @@ -3998,7 +4647,7 @@ } } - if (info->Clone) { + if (info->MergedFB) { PAL_SELECT(1); if (info->CurrentLayout.depth == 15) { /* 15bpp mode. This sends 32 values. */ @@ -4115,14 +4764,6 @@ pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); - if (info->CurCloneMode) { - info->CloneFrameX0 = - (pScrn->virtualX - info->CurCloneMode->HDisplay) / 2; - info->CloneFrameY0 = - (pScrn->virtualY - info->CurCloneMode->VDisplay) / 2; - RADEONDoAdjustFrame(pScrn, info->CloneFrameX0, info->CloneFrameY0, TRUE); - } - /* Visual setup */ miClearVisualTypes(); if (!miSetVisualTypes(pScrn->depth, @@ -4587,6 +5228,12 @@ info->CloseScreen = pScreen->CloseScreen; pScreen->CloseScreen = RADEONCloseScreen; + /* Wrap some funcs for MergedFB*/ + if(info->MergedFB) { + info->PointerMoved = pScrn->PointerMoved; + pScrn->PointerMoved = RADEONMergePointerMoved; + } + /* Note unused options */ if (serverGeneration == 1) xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); @@ -4643,7 +5290,7 @@ CARD32 tmp; RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - if (pRADEONEnt->HasSecondary || info->Clone) { + if (pRADEONEnt->HasSecondary || info->MergedFB) { tmp = INREG(RADEON_DAC_CNTL2); OUTREG(RADEON_DAC_CNTL2, tmp & ~RADEON_DAC2_DAC_CLK_SEL); usleep(100000); @@ -4736,7 +5383,7 @@ OUTREG(RADEON_CRTC2_OFFSET_CNTL, restore->crtc2_offset_cntl); OUTREG(RADEON_CRTC2_PITCH, restore->crtc2_pitch); - if (info->DisplayType == MT_DFP || info->CloneType == MT_DFP) { + if (info->DisplayType == MT_DFP || info->MergeType == MT_DFP) { OUTREG(RADEON_FP_H2_SYNC_STRT_WID, restore->fp2_h_sync_strt_wid); OUTREG(RADEON_FP_V2_SYNC_STRT_WID, restore->fp2_v_sync_strt_wid); OUTREG(RADEON_FP2_GEN_CNTL, restore->fp2_gen_cntl); @@ -5076,7 +5723,7 @@ if (!pRADEONEnt->IsSecondaryRestored) RADEONRestoreCommonRegisters(pScrn, restore); - if (info->Clone) { + if (info->MergedFB) { RADEONRestoreCrtc2Registers(pScrn, restore); RADEONRestorePLL2Registers(pScrn, restore); } @@ -5277,7 +5924,7 @@ RADEONSaveFPRegisters(pScrn, save); } - if (info->Clone) { + if (info->MergedFB) { RADEONSaveCrtc2Registers(pScrn, save); RADEONSavePLL2Registers(pScrn, save); } @@ -5354,7 +6001,7 @@ /* M6 card has trouble restoring text mode for its CRT. * This is fixed elsewhere and will be removed in the future. */ - if ((xf86IsEntityShared(info->pEnt->index) || info->Clone) + if ((xf86IsEntityShared(info->pEnt->index) || info->MergedFB) && info->IsM6) OUTREG(RADEON_DAC_CNTL2, restore->dac2_cntl); #endif @@ -5672,13 +6319,20 @@ save->crtc2_offset = 0; save->crtc2_offset_cntl = INREG(RADEON_CRTC2_OFFSET_CNTL); - + /* this should be right */ + if (info->MergedFB) { + save->crtc2_pitch = (((info->CRT2pScrn->displayWidth * pScrn->bitsPerPixel) + + ((pScrn->bitsPerPixel * 8) -1)) / + (pScrn->bitsPerPixel * 8)); + save->crtc2_pitch |= save->crtc2_pitch << 16; + } else { save->crtc2_pitch = (((pScrn->displayWidth * pScrn->bitsPerPixel) + ((pScrn->bitsPerPixel * 8) -1)) / (pScrn->bitsPerPixel * 8)); save->crtc2_pitch |= save->crtc2_pitch << 16; + } - if (info->DisplayType == MT_DFP || info->CloneType == MT_DFP) { + if (info->DisplayType == MT_DFP || info->MergeType == MT_DFP) { save->crtc2_gen_cntl = (RADEON_CRTC2_EN | (format << 8)); save->fp2_h_sync_strt_wid = save->crtc2_h_sync_strt_wid; save->fp2_v_sync_strt_wid = save->crtc2_v_sync_strt_wid; @@ -5851,7 +6505,7 @@ } save->tmds_transmitter_cntl= orig->tmds_transmitter_cntl; - if (info->PanelOff && info->Clone) { + if (info->PanelOff && info->MergedFB) { info->OverlayOnCRTC2 = TRUE; if (info->DisplayType == MT_LCD) { /* Turning off LVDS_ON seems to make panel white blooming. @@ -5869,7 +6523,7 @@ /* BIOS will use this setting to reset displays upon lid close/open. * Here we let BIOS controls LCD, but the driver will control the external CRT. */ - if (info->Clone || pRADEONEnt->HasSecondary) + if (info->MergedFB || pRADEONEnt->HasSecondary) save->bios_5_scratch = 0x01020201; else save->bios_5_scratch = orig->bios_5_scratch; @@ -6075,6 +6729,23 @@ if (!RADEONInitCrtc2Registers(pScrn, save, mode, info)) return FALSE; RADEONInitPLL2Registers(save, &info->pll, dot_clock); + } else if (info->MergedFB) { + RADEONInitCommonRegisters(save, info); + if (!RADEONInitCrtcRegisters(pScrn, save, + ((RADEONMergedDisplayModePtr)mode->Private)->CRT1, info)) + return FALSE; + dot_clock = (((RADEONMergedDisplayModePtr)mode->Private)->CRT1)->Clock / 1000.0; + if (dot_clock) { + RADEONInitPLLRegisters(save, &info->pll, dot_clock); + } else { + save->ppll_ref_div = info->SavedReg.ppll_ref_div; + save->ppll_div_3 = info->SavedReg.ppll_div_3; + save->htotal_cntl = info->SavedReg.htotal_cntl; + } + RADEONInitCrtc2Registers(pScrn, save, + ((RADEONMergedDisplayModePtr)mode->Private)->CRT2, info); + dot_clock = (((RADEONMergedDisplayModePtr)mode->Private)->CRT2)->Clock / 1000.0; + RADEONInitPLL2Registers(save, &info->pll, dot_clock); } else { RADEONInitCommonRegisters(save, info); if (!RADEONInitCrtcRegisters(pScrn, save, mode, info)) @@ -6094,11 +6765,6 @@ save->htotal_cntl = info->SavedReg.htotal_cntl; } - if (info->Clone && info->CurCloneMode) { - RADEONInitCrtc2Registers(pScrn, save, info->CurCloneMode, info); - dot_clock = info->CurCloneMode->Clock / 1000.0; - RADEONInitPLL2Registers(save, &info->pll, dot_clock); - } /* Not used for now: */ /* if (!info->PaletteSavedOnVT) RADEONInitPalette(save); */ } @@ -6164,56 +6830,7 @@ RADEONRestoreFBDevRegisters(pScrn, &info->ModeReg); } else { info->IsSwitching = TRUE; - if (info->Clone && info->CloneModes) { - DisplayModePtr clone_mode = info->CloneModes; - - /* Try to match a mode on primary head - * FIXME: This may not be good if both heads don't have - * exactly the same list of mode. - */ - while (1) { - if ((clone_mode->HDisplay == mode->HDisplay) && - (clone_mode->VDisplay == mode->VDisplay) && - (!info->PanelOff)) { - info->CloneFrameX0 = (info->CurCloneMode->HDisplay + - info->CloneFrameX0 - - clone_mode->HDisplay - 1) / 2; - info->CloneFrameY0 = - (info->CurCloneMode->VDisplay + info->CloneFrameY0 - - clone_mode->VDisplay - 1) / 2; - info->CurCloneMode = clone_mode; - break; - } - - if (!clone_mode->next) { - info->CurCloneMode = info->CloneModes; - break; - } - - clone_mode = clone_mode->next; - } - } ret = RADEONModeInit(xf86Screens[scrnIndex], mode); - - if (info->CurCloneMode) { - if (info->CloneFrameX0 + info->CurCloneMode->HDisplay >= - pScrn->virtualX) - info->CloneFrameX0 = - pScrn->virtualX - info->CurCloneMode->HDisplay; - else if (info->CloneFrameX0 < 0) - info->CloneFrameX0 = 0; - - if (info->CloneFrameY0 + info->CurCloneMode->VDisplay >= - pScrn->virtualY) - info->CloneFrameY0 = - pScrn->virtualY - info->CurCloneMode->VDisplay; - else if (info->CloneFrameY0 < 0) - info->CloneFrameY0 = 0; - - RADEONDoAdjustFrame(pScrn, info->CloneFrameX0, info->CloneFrameY0, - TRUE); - } - info->IsSwitching = FALSE; } @@ -6289,13 +6906,18 @@ pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); + if (clone || info->IsSecondary) { + pSAREAPriv->crtc2_base = Base; + } + if (pSAREAPriv->pfCurrentPage == 1) { Base += info->backOffset; } - +/* if (clone || info->IsSecondary) { pSAREAPriv->crtc2_base = Base; } +*/ } #endif @@ -6313,7 +6935,9 @@ if (info->accelOn) info->accel->Sync(pScrn); - if (info->FBDev) { + if(info->MergedFB) { + RADEONAdjustFrameMerged(scrnIndex, x, y, flags); + } else if (info->FBDev) { fbdevHWAdjustFrame(scrnIndex, x, y, flags); } else { RADEONDoAdjustFrame(pScrn, x, y, FALSE); @@ -6372,9 +6996,6 @@ #endif pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); - if (info->CurCloneMode) { - RADEONDoAdjustFrame(pScrn, info->CloneFrameX0, info->CloneFrameY0, TRUE); - } return TRUE; } @@ -6444,9 +7065,39 @@ if (info->DGAModes) xfree(info->DGAModes); info->DGAModes = NULL; - if (info->CloneModes) - while (info->CloneModes) - xf86DeleteMode(&info->CloneModes, info->CloneModes); + if(info->MergedFB) { + if(pScrn->modes) { + pScrn->currentMode = pScrn->modes; + do { + DisplayModePtr p = pScrn->currentMode->next; + if(pScrn->currentMode->Private) + xfree(pScrn->currentMode->Private); + xfree(pScrn->currentMode); + pScrn->currentMode = p; + } while(pScrn->currentMode != pScrn->modes); + } + pScrn->currentMode = info->CRT1CurrentMode; + pScrn->modes = info->CRT1Modes; + info->CRT1CurrentMode = NULL; + info->CRT1Modes = NULL; + + if(info->CRT2pScrn) { + if(info->CRT2pScrn->modes) { + while(info->CRT2pScrn->modes) + xf86DeleteMode(&info->CRT2pScrn->modes, info->CRT2pScrn->modes); + } + if(info->CRT2pScrn->monitor) { + if(info->CRT2pScrn->monitor->Modes) { + while(info->CRT2pScrn->monitor->Modes) + xf86DeleteMode(&info->CRT2pScrn->monitor->Modes, info->CRT2pScrn->monitor->Modes); + } + if(info->CRT2pScrn->monitor->DDC) xfree(info->CRT2pScrn->monitor->DDC); + xfree(info->CRT2pScrn->monitor); + } + xfree(info->CRT2pScrn); + info->CRT2pScrn = NULL; + } + } pScrn->vtSema = FALSE; @@ -6500,7 +7151,7 @@ if (info->IsSecondary) OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~mask2); else { - if (info->Clone) + if (info->MergedFB) OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~mask2); OUTREGP(RADEON_CRTC_EXT_CNTL, 0, ~mask1); } @@ -6513,7 +7164,7 @@ RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS, ~mask2); else { - if (info->Clone) + if (info->MergedFB) OUTREGP(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS, ~mask2); @@ -6530,7 +7181,7 @@ RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS, ~mask2); else { - if (info->Clone) + if (info->MergedFB) OUTREGP(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS, ~mask2); @@ -6545,7 +7196,7 @@ if (info->IsSecondary) OUTREGP(RADEON_CRTC2_GEN_CNTL, mask2, ~mask2); else { - if (info->Clone) + if (info->MergedFB) OUTREGP(RADEON_CRTC2_GEN_CNTL, mask2, ~mask2); OUTREGP(RADEON_CRTC_EXT_CNTL, mask1, ~mask1); } --- ../ati.orig/radeon.h 2003-04-06 21:22:09.000000000 -0400 +++ ./radeon.h 2003-05-20 00:29:26.000000000 -0400 @@ -263,6 +263,15 @@ CHIP_FAMILY_R300 } RADEONChipFamily; +/* Relative merge position */ +typedef enum { + radeonLeftOf, + radeonRightOf, + radeonAbove, + radeonBelow, + radeonClone +} RADEONScrn2Rel; + typedef struct { EntityInfoPtr pEnt; pciVideoPtr PciInfo; @@ -293,13 +302,6 @@ Bool IsMobility; /* Mobile chips for laptops */ Bool IsSecondary; /* Second Screen */ Bool IsSwitching; /* Flag for switching mode */ - Bool Clone; /* Force second head to clone primary*/ - RADEONMonitorType CloneType; - RADEONDDCType CloneDDCType; - DisplayModePtr CloneModes; - DisplayModePtr CurCloneMode; - int CloneFrameX0; - int CloneFrameY0; Bool OverlayOnCRTC2; Bool PanelOff; /* Force panel (LCD/DFP) off */ int FPBIOSstart; /* Start of the flat panel info */ @@ -538,8 +540,51 @@ #ifdef XFree86LOADER XF86ModReqInfo xaaReq; #endif + + /* merged fb stuff, also covers clone modes */ + Bool MergedFB; + RADEONScrn2Rel CRT2Position; + char * CRT2HSync; + char * CRT2VRefresh; + char * MetaModes; + ScrnInfoPtr CRT2pScrn; + DisplayModePtr CRT1Modes; + DisplayModePtr CRT1CurrentMode; + int CRT1frameX0; + int CRT1frameY0; + int CRT1frameX1; + int CRT1frameY1; + RADEONMonitorType MergeType; + RADEONDDCType MergeDDCType; + void (*PointerMoved)(int index, int x, int y); + } RADEONInfoRec, *RADEONInfoPtr; +#define SDMPTR(x) ((RADEONMergedDisplayModePtr)(x->currentMode->Private)) +#define CDMPTR ((RADEONMergedDisplayModePtr)(info->CurrentLayout.mode->Private)) + +#define BOUND(test,low,hi) { \ + if(test < low) test = low; \ + if(test > hi) test = hi; } + +#define REBOUND(low,hi,test) { \ + if(test < low) { \ + hi += test-low; \ + low = test; } \ + if(test > hi) { \ + low += test-hi; \ + hi = test; } } + +typedef struct _MergedDisplayModeRec { + DisplayModePtr CRT1; + DisplayModePtr CRT2; + RADEONScrn2Rel CRT2Position; +} RADEONMergedDisplayModeRec, *RADEONMergedDisplayModePtr; + +typedef struct _region { + int x0,x1,y0,y1; +} region; + #define RADEONWaitForFifo(pScrn, entries) \ do { \ if (info->fifo_slots < entries) \ --- ../ati.orig/radeon_video.c 2003-04-23 17:51:31.000000000 -0400 +++ ./radeon_video.c 2003-05-20 00:29:26.000000000 -0400 @@ -926,6 +926,7 @@ * at the same time, we might need to consider using software * rendering for the second head. */ +#if 0 if ((info->Clone && info->OverlayOnCRTC2) || info->IsSecondary) { x_off = 0; OUTREG(RADEON_OV1_Y_X_START, ((dstBox->x1 @@ -943,6 +944,16 @@ - info->CloneFrameY0 + pScrn->frameY0) << 16))); scaler_src = (1 << 14); +#endif + /* this might not be right... */ + if ((info->MergedFB && info->OverlayOnCRTC2) || info->IsSecondary) { + x_off = 0; + OUTREG(RADEON_OV1_Y_X_START, ((dstBox->x1 + x_off) | + ((dstBox->y1*y_mult) << 16))); + + OUTREG(RADEON_OV1_Y_X_END, ((dstBox->x2 + x_off) | + ((dstBox->y2*y_mult) << 16))); + scaler_src = (1 << 14); } else { OUTREG(RADEON_OV0_Y_X_START, ((dstBox->x1 + x_off) | ((dstBox->y1*y_mult) << 16)));