From: "Antonino A. Daplas" <adaplas@hotpop.com>

The patch below fixes the following to rivafb:

1 Seems that nVidia hardware has a limit on clipping coordinates that is
  also dependent on the color depth of the framebuffer.

2.From Pawel Goleniowski <pawelg@dabrowa.pl>: Fix for wrong colors at 16bpp
  (RGB565).  The fix has been submitted several times in lkml and this list
  but was never applied.

3 Search all I2C/DDC busses for the EDID block instead of just the first
  bus.

4 Updated request_mem_region/release_mem_region to
  pci_request_regions/pci_release_regions.

Signed-off-by: Antonino Daplas <adaplas@pol.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/drivers/video/riva/fbdev.c  |   95 ++++++++++++++++++------------------
 25-akpm/drivers/video/riva/rivafb.h |    1 
 2 files changed, 51 insertions(+), 45 deletions(-)

diff -puN drivers/video/riva/fbdev.c~rivafb-fixes drivers/video/riva/fbdev.c
--- 25/drivers/video/riva/fbdev.c~rivafb-fixes	2004-06-29 22:32:10.395635520 -0700
+++ 25-akpm/drivers/video/riva/fbdev.c	2004-06-29 22:32:10.402634456 -0700
@@ -882,13 +882,13 @@ static int rivafb_do_maximize(struct fb_
 		       var->xres_virtual, var->yres_virtual);
 	} else if (var->xres_virtual == -1) {
 		var->xres_virtual = (info->fix.smem_len * den /
-			(nom * var->yres_virtual * 2)) & ~15;
+			(nom * var->yres_virtual)) & ~15;
 		printk(KERN_WARNING PFX
 		       "setting virtual X resolution to %d\n", var->xres_virtual);
 	} else if (var->yres_virtual == -1) {
 		var->xres_virtual = (var->xres_virtual + 15) & ~15;
 		var->yres_virtual = info->fix.smem_len * den /
-			(nom * var->xres_virtual * 2);
+			(nom * var->xres_virtual);
 		printk(KERN_WARNING PFX
 		       "setting virtual Y resolution to %d\n", var->yres_virtual);
 	} else {
@@ -920,10 +920,11 @@ static int rivafb_do_maximize(struct fb_
 		       "virtual Y resolution (%d) is smaller than real\n", var->yres_virtual);
 		return -EINVAL;
 	}
-	if (var->xres_virtual > 0x7fff)
-	    var->xres_virtual = 0x7fff;
-	if (var->yres_virtual > 0x7fff)
-	    var->yres_virtual = 0x7fff;
+	if (var->yres_virtual > 0x7fff/nom)
+		var->yres_virtual = 0x7fff/nom;
+	if (var->xres_virtual > 0x7fff/nom)
+		var->xres_virtual = 0x7fff/nom;
+
 	return 0;
 }
 
@@ -955,11 +956,14 @@ riva_set_rop_solid(struct riva_par *par,
 
 }
 
-void riva_setup_accel(struct riva_par *par)
+void riva_setup_accel(struct fb_info *info)
 {
+	struct riva_par *par = (struct riva_par *) info->par;
+
 	RIVA_FIFO_FREE(par->riva, Clip, 2);
 	par->riva.Clip->TopLeft     = 0x0;
-	par->riva.Clip->WidthHeight = 0x7fff7fff;
+	par->riva.Clip->WidthHeight = (info->var.xres_virtual & 0xffff) |
+		(info->var.yres_virtual << 16);
 	riva_set_rop_solid(par, 0xcc);
 	wait_for_idle(par);
 }
@@ -1194,9 +1198,16 @@ static int rivafb_set_par(struct fb_info
 {
 	struct riva_par *par = (struct riva_par *) info->par;
 
+	riva_common_setup(par);
+	RivaGetConfig(&par->riva, par->Chipset);
+	/* vgaHWunlock() + riva unlock (0x7F) */
+	CRTCout(par, 0x11, 0xFF);
+	par->riva.LockUnlock(&par->riva, 0);
+
 	riva_load_video_mode(info);
-	riva_setup_accel(par);
+	riva_setup_accel(info);
 	
+	memset_io(par->riva.CURSOR, 0, MAX_CURS * MAX_CURS * 2);
 	info->fix.line_length = (info->var.xres_virtual * (info->var.bits_per_pixel >> 3));
 	info->fix.visual = (info->var.bits_per_pixel == 8) ?
 				FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
@@ -1444,8 +1455,8 @@ static void rivafb_copyarea(struct fb_in
 
 static inline void convert_bgcolor_16(u32 *col)
 {
-	*col = ((*col & 0x00007C00) << 9)
-		| ((*col & 0x000003E0) << 6)
+	*col = ((*col & 0x0000F800) << 8)
+		| ((*col & 0x00007E0) << 5)
 		| ((*col & 0x0000001F) << 3)
 		|	   0xFF000000;
 	mb();
@@ -1759,9 +1770,16 @@ static void riva_get_EDID(struct fb_info
 	/* XXX use other methods later */
 #ifdef CONFIG_FB_RIVA_I2C
 	struct riva_par *par = (struct riva_par *) info->par;
+	int i;
 
 	riva_create_i2c_busses(par);
-	riva_probe_i2c_connector(par, 1, &par->EDID);
+	for (i = par->bus; i >= 1; i--) {
+		riva_probe_i2c_connector(par, i, &par->EDID);
+		if (par->EDID) {
+			printk("rivafb: Found EDID Block from BUS %i\n", i);
+			break;
+		}
+	}
 	riva_delete_i2c_busses(par);
 #endif
 #endif
@@ -1814,6 +1832,16 @@ static int __devinit rivafb_probe(struct
 		goto err_out_kfree1;
 	memset(info->pixmap.addr, 0, 64 * 1024);
 
+	if (pci_enable_device(pd)) {
+		printk(KERN_ERR PFX "cannot enable PCI device\n");
+		goto err_out_enable;
+	}
+
+	if (pci_request_regions(pd, "rivafb")) {
+		printk(KERN_ERR PFX "cannot request PCI regions\n");
+		goto err_out_request;
+	}
+
 	strcat(rivafb_fix.id, rci->name);
 	default_par->riva.Architecture = rci->arch_rev;
 
@@ -1840,12 +1868,6 @@ static int __devinit rivafb_probe(struct
 	rivafb_fix.mmio_start = pci_resource_start(pd, 0);
 	rivafb_fix.smem_start = pci_resource_start(pd, 1);
 
-	if (!request_mem_region(rivafb_fix.mmio_start,
-				rivafb_fix.mmio_len, "rivafb")) {
-		printk(KERN_ERR PFX "cannot reserve MMIO region\n");
-		goto err_out_kfree2;
-	}
-
 	default_par->ctrl_base = ioremap(rivafb_fix.mmio_start,
 					 rivafb_fix.mmio_len);
 	if (!default_par->ctrl_base) {
@@ -1861,17 +1883,13 @@ static int __devinit rivafb_probe(struct
 		 * Since these cards were never made with more than 8 megabytes
 		 * we can safely allocate this separately.
 		 */
-		if (!request_mem_region(rivafb_fix.smem_start + 0x00C00000,
-					 0x00008000, "rivafb")) {
-			printk(KERN_ERR PFX "cannot reserve PRAMIN region\n");
-			goto err_out_iounmap_ctrl;
-		}
 		default_par->riva.PRAMIN = ioremap(rivafb_fix.smem_start + 0x00C00000, 0x00008000);
 		if (!default_par->riva.PRAMIN) {
 			printk(KERN_ERR PFX "cannot ioremap PRAMIN region\n");
 			goto err_out_free_nv3_pramin;
 		}
 		rivafb_fix.accel = FB_ACCEL_NV3;
+		default_par->bus = 1;
 		break;
 	case NV_ARCH_04:
 	case NV_ARCH_10:
@@ -1879,6 +1897,7 @@ static int __devinit rivafb_probe(struct
 		default_par->riva.PCRTC0 = (unsigned *)(default_par->ctrl_base + 0x00600000);
 		default_par->riva.PRAMIN = (unsigned *)(default_par->ctrl_base + 0x00710000);
 		rivafb_fix.accel = FB_ACCEL_NV4;
+		default_par->bus = 2;
 		break;
 	}
 
@@ -1891,12 +1910,6 @@ static int __devinit rivafb_probe(struct
 	rivafb_fix.smem_len = riva_get_memlen(default_par) * 1024;
 	default_par->dclk_max = riva_get_maxdclk(default_par) * 1000;
 
-	if (!request_mem_region(rivafb_fix.smem_start,
-				rivafb_fix.smem_len, "rivafb")) {
-		printk(KERN_ERR PFX "cannot reserve FB region\n");
-		goto err_out_iounmap_nv3_pramin;
-	}
-	
 	info->screen_base = ioremap(rivafb_fix.smem_start,
 				    rivafb_fix.smem_len);
 	if (!info->screen_base) {
@@ -1949,18 +1962,15 @@ static int __devinit rivafb_probe(struct
 err_out_iounmap_fb:
 	iounmap(info->screen_base);
 err_out_free_base1:
-	release_mem_region(rivafb_fix.smem_start, rivafb_fix.smem_len);
-err_out_iounmap_nv3_pramin:
 	if (default_par->riva.Architecture == NV_ARCH_03) 
 		iounmap((caddr_t)default_par->riva.PRAMIN);
 err_out_free_nv3_pramin:
-	if (default_par->riva.Architecture == NV_ARCH_03)
-		release_mem_region(rivafb_fix.smem_start + 0x00C00000, 0x00008000);
-err_out_iounmap_ctrl:
 	iounmap(default_par->ctrl_base);
 err_out_free_base0:
-	release_mem_region(rivafb_fix.mmio_start, rivafb_fix.mmio_len);
-err_out_kfree2:
+	pci_release_regions(pd);
+err_out_request:
+	pci_disable_device(pd);
+err_out_enable:
 	kfree(info->pixmap.addr);
 err_out_kfree1:
 	kfree(default_par);
@@ -1987,16 +1997,11 @@ static void __exit rivafb_remove(struct 
 
 	iounmap(par->ctrl_base);
 	iounmap(info->screen_base);
-
-	release_mem_region(info->fix.mmio_start,
-			   info->fix.mmio_len);
-	release_mem_region(info->fix.smem_start,
-			   info->fix.smem_len);
-
-	if (par->riva.Architecture == NV_ARCH_03) {
+	if (par->riva.Architecture == NV_ARCH_03)
 		iounmap((caddr_t)par->riva.PRAMIN);
-		release_mem_region(info->fix.smem_start + 0x00C00000, 0x00008000);
-	}
+	pci_release_regions(pd);
+	pci_disable_device(pd);
+	fb_destroy_modedb(info->monspecs.modedb);
 	kfree(info->pixmap.addr);
 	kfree(par);
 	kfree(info);
diff -puN drivers/video/riva/rivafb.h~rivafb-fixes drivers/video/riva/rivafb.h
--- 25/drivers/video/riva/rivafb.h~rivafb-fixes	2004-06-29 22:32:10.396635368 -0700
+++ 25-akpm/drivers/video/riva/rivafb.h	2004-06-29 22:32:10.403634304 -0700
@@ -60,6 +60,7 @@ struct riva_par {
 	Bool SecondCRTC;
 	int FlatPanel;
 	struct pci_dev *pdev;
+	int bus;
 #ifdef CONFIG_MTRR
 	struct { int vram; int vram_valid; } mtrr;
 #endif
_