File 0001-s2disk-ddx-with-xorg-option.patch of Package nouveau

diff --git a/src/nv30_shaders.c b/src/nv30_shaders.c
index 735b454..effec7b 100644
--- a/src/nv30_shaders.c
+++ b/src/nv30_shaders.c
@@ -23,6 +23,8 @@
 
 #include "nv30_shaders.h"
 
+struct nouveau_bo *global_fp_mem = NULL;
+
 void
 NV30_LoadFragProg(ScrnInfoPtr pScrn, nv_shader_t *shader)
 {
@@ -44,6 +46,7 @@ NV30_LoadFragProg(ScrnInfoPtr pScrn, nv_shader_t *shader)
 			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 				   "Couldn't map fragprog buffer!\n");
 		}
+		global_fp_mem = fp_mem;
 	}
 
 	if (!shader->hw_id) {
@@ -133,6 +136,7 @@ NV40_LoadFragProg(ScrnInfoPtr pScrn, nv_shader_t *shader)
 			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 				   "Couldn't map fragprog buffer!\n");
 		}
+		global_fp_mem = fp_mem;
 	}
 
 	if (!shader->hw_id) {
diff --git a/src/nv_const.h b/src/nv_const.h
index 9d0b997..86155b0 100644
--- a/src/nv_const.h
+++ b/src/nv_const.h
@@ -32,6 +32,7 @@ typedef enum {
     OPTION_SCALING_MODE,
     OPTION_NEW_RESTORE,
     OPTION_KMS,
+    OPTION_S2DISK,
 } NVOpts;
 
 
@@ -53,6 +54,7 @@ static const OptionInfoRec NVOptions[] = {
     { OPTION_SCALING_MODE,	"ScalingMode",	OPTV_STRING,	{0}, FALSE },
     { OPTION_NEW_RESTORE,	"NewRestore",	OPTV_BOOLEAN,	{0}, FALSE },
     { OPTION_KMS,	"KMS",	OPTV_BOOLEAN,	{0}, FALSE },
+    { OPTION_S2DISK,	"Suspend2disk",	OPTV_BOOLEAN,	{0}, FALSE },
     { -1,                       NULL,           OPTV_NONE,      {0}, FALSE }
 };
 
diff --git a/src/nv_driver.c b/src/nv_driver.c
index 3b201bf..5ad2ec8 100644
--- a/src/nv_driver.c
+++ b/src/nv_driver.c
@@ -28,6 +28,14 @@
 
 #include "xf86drm.h"
 
+/* the modesetting stuff is on crack and calls EnterVT at times other than when
+ * the X VT has been entered. bonged distinguishes this case
+ */
+static int bonged = 0;
+/* Uh, yeah */
+extern struct nouveau_bo *global_fp_mem;
+static uint32_t fp_backup[0x1000/4];
+
 extern DisplayModePtr xf86ModesAdd(DisplayModePtr Modes, DisplayModePtr Additions);
 
 /*
@@ -705,6 +713,16 @@ NVEnterVT(int scrnIndex, int flags)
 	NVPtr pNv = NVPTR(pScrn);
 
 	if (!pNv->kms_enable) {
+		if (pNv->s2disk_enable && !bonged) {
+			if (global_fp_mem) {
+				uint32_t i, *map = global_fp_mem->map;
+				for (i = 0; i < 0x1000/4; i++)
+					map[i] = fp_backup[i];
+			}
+
+			drmCommandNone(((struct nouveau_device_priv *)pNv->dev)->fd, DRM_NOUVEAU_RESUME);
+		}
+
 		if (pNv->randr12_enable) {
 			xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NVEnterVT is called.\n");
 			xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
@@ -729,6 +747,8 @@ NVEnterVT(int scrnIndex, int flags)
 
 			if (!xf86SetDesiredModes(pScrn))
 				return FALSE;
+
+			NVAccelCommonInit(pScrn);
 		} else {
 			if (!NVModeInit(pScrn, pScrn->currentMode))
 				return FALSE;
@@ -1633,6 +1653,29 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
 			NVPreInitFail("\n");
 		}
 		xf86LoaderReqSymLists(exaSymbols, NULL);
+
+		if (xf86ReturnOptValBool(pNv->Options, OPTION_S2DISK, FALSE))
+			pNv->s2disk_enable = TRUE;
+
+		if (pNv->Architecture >= NV_ARCH_50) {
+			xf86DrvMsg(pScrn->scrnIndex, from,
+				"s2disk not implemented for nv50 (ask darktama for help or use ShadowFB)!\n");
+			pNv->s2disk_enable = FALSE;
+		}
+
+		xf86DrvMsg(pScrn->scrnIndex, from,
+			"New (experimental) support for suspend to disk %sabled\n",
+			pNv->s2disk_enable ? "en" : "dis");
+
+		if (pNv->s2disk_enable) {
+			uint64_t res;
+
+			xf86DrvMsg(pScrn->scrnIndex, from,
+				"NOTE: Switch to a text console before the kernel suspends to disk!\n");
+			if (pNv->Architecture >= NV_ARCH_40)
+				xf86DrvMsg(pScrn->scrnIndex, from,
+					"NOTE: Switch to a text console will take a few seconds (copies 16MiB RAMIN)!\n");
+		}
 	}
 
 	/* Load ramdac if needed */
@@ -2104,6 +2152,16 @@ NVRestore(ScrnInfoPtr pScrn)
 		NVWriteVgaCrtc(pNv, 0, NV_VGA_CRTCX_OWNER, pNv->vtOWNER);
 		NVLockVgaCrtc(pNv, 0, true);
 	}
+
+	if (pNv->s2disk_enable) {
+		drmCommandNone(((struct nouveau_device_priv *)pNv->dev)->fd, DRM_NOUVEAU_SUSPEND);
+
+		if (global_fp_mem) {
+			uint32_t i, *map = global_fp_mem->map;
+			for (i = 0; i < 0x1000/4; i++)
+				fp_backup[i] = map[i];
+		}
+	}
 }
 
 static void
@@ -2383,8 +2441,10 @@ NVScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
 			xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CRTC 1 was enabled.\n");
 		}
 
+		bonged = 1;
 		if (!NVEnterVT(scrnIndex, 0))
 			return FALSE;
+		bonged = 0;
 		NVSaveScreen(pScreen, SCREEN_SAVER_ON);
 	}
 
@@ -2489,7 +2549,6 @@ NVScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
 	if (!pNv->NoAccel) {
 		if (!NVExaInit(pScreen))
 			return FALSE;
-		NVAccelCommonInit(pScrn);
 	} else if (pNv->VRAMPhysicalSize / 2 < NOUVEAU_ALIGN(pScrn->virtualX, 64) * NOUVEAU_ALIGN(pScrn->virtualY, 64) * (pScrn->bitsPerPixel >> 3)) {
 		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "The virtual screen size's resolution is too big for the video RAM framebuffer at this colour depth.\n");
 		return FALSE;
diff --git a/src/nv_type.h b/src/nv_type.h
index 11c0be0..7e2c31c 100644
--- a/src/nv_type.h
+++ b/src/nv_type.h
@@ -470,6 +470,7 @@ typedef struct _NVRec {
 	Bool randr12_enable;
 	Bool kms_enable;
 	Bool new_restore;
+	Bool s2disk_enable;
 
 	I2CBusPtr           pI2CBus[MAX_NUM_DCB_ENTRIES];
 
openSUSE Build Service is sponsored by