diff --git a/drivers/video/nvidia/nv_hw.c b/drivers/video/nvidia/nv_hw.c
index b989358437b3723e4e26dddb4b597b85c411fccb..454283f9bdac2aafe2ca457b1f4608384a26f94c 100644
--- a/drivers/video/nvidia/nv_hw.c
+++ b/drivers/video/nvidia/nv_hw.c
@@ -848,7 +848,7 @@ void NVCalcStateExt(struct nvidia_par *par,
 		    int width,
 		    int hDisplaySize, int height, int dotClock, int flags)
 {
-	int pixelDepth, VClk;
+	int pixelDepth, VClk = 0;
 	/*
 	 * Save mode parameters.
 	 */
@@ -938,15 +938,24 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
 
 	if (par->Architecture == NV_ARCH_04) {
 		NV_WR32(par->PFB, 0x0200, state->config);
-	} else if ((par->Chipset & 0xfff0) == 0x0090) {
-		for (i = 0; i < 15; i++) {
-			NV_WR32(par->PFB, 0x0600 + (i * 0x10), 0);
-			NV_WR32(par->PFB, 0x0604 + (i * 0x10), par->FbMapSize - 1);
-		}
-	} else {
+	} else if ((par->Architecture < NV_ARCH_40) ||
+		   (par->Chipset & 0xfff0) == 0x0040) {
 		for (i = 0; i < 8; i++) {
 			NV_WR32(par->PFB, 0x0240 + (i * 0x10), 0);
-			NV_WR32(par->PFB, 0x0244 + (i * 0x10), par->FbMapSize - 1);
+			NV_WR32(par->PFB, 0x0244 + (i * 0x10),
+				par->FbMapSize - 1);
+		}
+	} else {
+		int regions = 12;
+
+		if (((par->Chipset & 0xfff0) == 0x0090) ||
+		    ((par->Chipset & 0xfff0) == 0x01D0) ||
+		    ((par->Chipset & 0xfff0) == 0x0290))
+			regions = 15;
+		for(i = 0; i < regions; i++) {
+			NV_WR32(par->PFB, 0x0600 + (i * 0x10), 0);
+			NV_WR32(par->PFB, 0x0604 + (i * 0x10),
+				par->FbMapSize - 1);
 		}
 	}
 
@@ -1182,11 +1191,17 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
 			NV_WR32(par->PGRAPH, 0x0608, 0xFFFFFFFF);
 		} else {
 			if (par->Architecture >= NV_ARCH_40) {
+				u32 tmp;
+
 				NV_WR32(par->PGRAPH, 0x0084, 0x401287c0);
 				NV_WR32(par->PGRAPH, 0x008C, 0x60de8051);
 				NV_WR32(par->PGRAPH, 0x0090, 0x00008000);
 				NV_WR32(par->PGRAPH, 0x0610, 0x00be3c5f);
 
+				tmp = NV_RD32(par->REGS, 0x1540) & 0xff;
+				for(i = 0; tmp && !(tmp & 1); tmp >>= 1, i++);
+				NV_WR32(par->PGRAPH, 0x5000, i);
+
 				if ((par->Chipset & 0xfff0) == 0x0040) {
 					NV_WR32(par->PGRAPH, 0x09b0,
 						0x83280fff);
@@ -1211,6 +1226,7 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
 						0xffff7fff);
 					break;
 				case 0x00C0:
+				case 0x0120:
 					NV_WR32(par->PGRAPH, 0x0828,
 						0x007596ff);
 					NV_WR32(par->PGRAPH, 0x082C,
@@ -1245,6 +1261,7 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
 						0x00100000);
 					break;
 				case 0x0090:
+				case 0x0290:
 					NV_WR32(par->PRAMDAC, 0x0608,
 						NV_RD32(par->PRAMDAC, 0x0608) |
 						0x00100000);
@@ -1310,14 +1327,44 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
 				}
 			}
 
-			if ((par->Chipset & 0xfff0) == 0x0090) {
-				for (i = 0; i < 60; i++)
-					NV_WR32(par->PGRAPH, 0x0D00 + i,
-						NV_RD32(par->PFB, 0x0600 + i));
+			if ((par->Architecture < NV_ARCH_40) ||
+			    ((par->Chipset & 0xfff0) == 0x0040)) {
+				for (i = 0; i < 32; i++) {
+					NV_WR32(par->PGRAPH, 0x0900 + i*4,
+						NV_RD32(par->PFB, 0x0240 +i*4));
+					NV_WR32(par->PGRAPH, 0x6900 + i*4,
+						NV_RD32(par->PFB, 0x0240 +i*4));
+				}
 			} else {
-				for (i = 0; i < 32; i++)
-					NV_WR32(par->PGRAPH, 0x0900 + i,
-						NV_RD32(par->PFB, 0x0240 + i));
+				if (((par->Chipset & 0xfff0) == 0x0090) ||
+				    ((par->Chipset & 0xfff0) == 0x01D0) ||
+				    ((par->Chipset & 0xfff0) == 0x0290)) {
+					for (i = 0; i < 60; i++) {
+						NV_WR32(par->PGRAPH,
+							0x0D00 + i*4,
+							NV_RD32(par->PFB,
+								0x0600 + i*4));
+						NV_WR32(par->PGRAPH,
+							0x6900 + i*4,
+							NV_RD32(par->PFB,
+								0x0600 + i*4));
+					}
+				} else {
+					for (i = 0; i < 48; i++) {
+						NV_WR32(par->PGRAPH,
+							0x0900 + i*4,
+							NV_RD32(par->PFB,
+								0x0600 + i*4));
+						if(((par->Chipset & 0xfff0)
+						    != 0x0160) &&
+						   ((par->Chipset & 0xfff0)
+						    != 0x0220))
+							NV_WR32(par->PGRAPH,
+								0x6900 + i*4,
+								NV_RD32(par->PFB,
+									0x0600 + i*4));
+					}
+				}
 			}
 
 			if (par->Architecture >= NV_ARCH_40) {
@@ -1338,7 +1385,9 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
 					NV_WR32(par->PGRAPH, 0x0868,
 						par->FbMapSize - 1);
 				} else {
-					if((par->Chipset & 0xfff0) == 0x0090) {
+					if ((par->Chipset & 0xfff0) == 0x0090 ||
+					    (par->Chipset & 0xfff0) == 0x01D0 ||
+					    (par->Chipset & 0xfff0) == 0x0290) {
 						NV_WR32(par->PGRAPH, 0x0DF0,
 							NV_RD32(par->PFB, 0x0200));
 						NV_WR32(par->PGRAPH, 0x0DF4,
diff --git a/drivers/video/nvidia/nv_setup.c b/drivers/video/nvidia/nv_setup.c
index 1f06a9f1bd0f52d893e4233111174281a23f130e..2c024523c6222bb2100ed2c34eff39ba300c1912 100644
--- a/drivers/video/nvidia/nv_setup.c
+++ b/drivers/video/nvidia/nv_setup.c
@@ -285,7 +285,6 @@ static void nv10GetConfig(struct nvidia_par *par)
 			par->CrystalFreqKHz = 27000;
 	}
 
-	par->CursorStart = (par->RamAmountKBytes - 96) * 1024;
 	par->CURSOR = NULL;	/* can't set this here */
 	par->MinVClockFreqKHz = 12000;
 	par->MaxVClockFreqKHz = par->twoStagePLL ? 400000 : 350000;
@@ -382,6 +381,8 @@ void NVCommonSetup(struct fb_info *info)
 	case 0x0146:
 	case 0x0147:
 	case 0x0148:
+	case 0x0098:
+	case 0x0099:
 		mobile = 1;
 		break;
 	default:
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index bee09c6e48f61ce28224fa2282f6bd8f113f114a..f6d2440e84aaf4c0a7ea7df39b8d9fe1ccdcfa64 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -1485,6 +1485,8 @@ static u32 __devinit nvidia_get_arch(struct pci_dev *pd)
 	case 0x0210:
 	case 0x0220:
 	case 0x0230:
+	case 0x0290:
+	case 0x0390:
 		arch = NV_ARCH_40;
 		break;
 	case 0x0020:		/* TNT, TNT2 */
@@ -1581,10 +1583,15 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd,
 	if (par->FbMapSize > 64 * 1024 * 1024)
 		par->FbMapSize = 64 * 1024 * 1024;
 
-	par->FbUsableSize = par->FbMapSize - (128 * 1024);
+	if(par->Architecture >= NV_ARCH_40)
+  	        par->FbUsableSize = par->FbMapSize - (560 * 1024);
+	else
+		par->FbUsableSize = par->FbMapSize - (128 * 1024);
 	par->ScratchBufferSize = (par->Architecture < NV_ARCH_10) ? 8 * 1024 :
 	    16 * 1024;
 	par->ScratchBufferStart = par->FbUsableSize - par->ScratchBufferSize;
+	par->CursorStart = par->FbUsableSize + (32 * 1024);
+
 	info->screen_base = ioremap(nvidiafb_fix.smem_start, par->FbMapSize);
 	info->screen_size = par->FbUsableSize;
 	nvidiafb_fix.smem_len = par->RamAmountKBytes * 1024;