--- ../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-05-30 20:09:07.000000000 -0400
@@ -139,11 +139,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 +171,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 +547,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 +782,7 @@
 	default:
 	    break;
 	}
-	if (info->Clone)
+	if (info->MergedFB)
 	    OUTREGP(RADEON_CRTC2_GEN_CNTL,
 		    RADEON_CRTC2_DISP_DIS |
 		    RADEON_CRTC2_VSYNC_DIS |
@@ -777,7 +823,7 @@
 	default:
 	    break;
 	}
-	if (info->Clone)
+	if (info->MergedFB)
 	    OUTREGP(RADEON_CRTC2_GEN_CNTL,
 		    0,
 		    ~(RADEON_CRTC2_DISP_DIS |
@@ -818,6 +864,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 +2006,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 +2016,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 +2028,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 +2627,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 +3496,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 +3509,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 +3521,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 +3536,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,22 +3558,22 @@
     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;
@@ -3084,14 +3591,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 +3613,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 +3628,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 +3641,55 @@
                                       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;
+    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 +3707,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 */
@@ -3280,24 +3798,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,30 +3978,71 @@
 
     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(info->MergedFB) {
+       xf86SetDpi(info->CRT2pScrn, 0, 0);
+    }
 
 				/* Get ScreenInit function */
 #ifdef USE_FB
@@ -3725,6 +4283,7 @@
     RADEONInfoPtr     info;
     xf86Int10InfoPtr  pInt10 = NULL;
     void *int10_save = NULL;
+    char        *strptr;
     
     RADEONTRACE(("RADEONPreInit\n"));
     if (pScrn->numEntities != 1) return FALSE;
@@ -3733,9 +4292,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 +4414,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 +4638,7 @@
 	    }
 	}
 
-	if (info->Clone) {
+	if (info->MergedFB) {
 	    PAL_SELECT(1);
 	    if (info->CurrentLayout.depth == 15) {
 		/* 15bpp mode.  This sends 32 values. */
@@ -4115,14 +4755,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 +5219,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 +5281,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 +5374,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 +5714,7 @@
 	if (!pRADEONEnt->IsSecondaryRestored)
 	    RADEONRestoreCommonRegisters(pScrn, restore);
 
-	if (info->Clone) {
+	if (info->MergedFB) {
 	    RADEONRestoreCrtc2Registers(pScrn, restore);
 	    RADEONRestorePLL2Registers(pScrn, restore);
 	}
@@ -5277,7 +5915,7 @@
 	    RADEONSaveFPRegisters(pScrn, save);
 	}
 
-	if (info->Clone) {
+	if (info->MergedFB) {
 	    RADEONSaveCrtc2Registers(pScrn, save);
 	    RADEONSavePLL2Registers(pScrn, save);
 	}
@@ -5354,7 +5992,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 +6310,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 +6496,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 +6514,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 +6720,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 +6756,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 +6821,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;
     }
 
@@ -6313,6 +6921,11 @@
 
     if (info->accelOn) info->accel->Sync(pScrn);
 
+    if(info->MergedFB) {
+    	RADEONAdjustFrameMerged(scrnIndex, x, y, flags);
+	return;
+    }
+
     if (info->FBDev) {
 	fbdevHWAdjustFrame(scrnIndex, x, y, flags);
     } else {
@@ -6372,9 +6985,6 @@
 #endif
 
     pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
-    if (info->CurCloneMode) {
-	RADEONDoAdjustFrame(pScrn, info->CloneFrameX0, info->CloneFrameY0, TRUE);
-    }
 
     return TRUE;
 }
@@ -6444,9 +7054,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 +7140,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 +7153,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 +7170,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 +7185,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)));
