fbdev: Convert a few drivers to use the fb_find_best_display helper
Convert i810fb, nvidiafb and savagefb to use the fb_find_best_display
helper when searching for the initial video mode.

Signed-off-by: Antonino Daplas <adaplas@pol.net>

Index: git/drivers/video/Kconfig
===================================================================
--- git.orig/drivers/video/Kconfig	2005-10-30 17:09:45.000000000 +0000
+++ git/drivers/video/Kconfig	2005-10-30 17:11:09.000000000 +0000
@@ -1299,7 +1299,6 @@
 	depends on FB_SBUS && SPARC64
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
-	select FB_SOFT_CURSOR
 	help
 	  This is the frame buffer device driver for the Creator, Creator3D,
 	  and Elite3D graphics boards.
Index: git/drivers/video/fbmon.c
===================================================================
--- git.orig/drivers/video/fbmon.c	2005-10-30 17:09:38.000000000 +0000
+++ git/drivers/video/fbmon.c	2005-10-30 17:11:09.000000000 +0000
@@ -538,25 +538,12 @@
 
 	*dbsize = 0;
 
-	DPRINTK("   Supported VESA Modes\n");
-	block = edid + ESTABLISHED_TIMING_1;
-	num += get_est_timing(block, &mode[num]);
-
-	DPRINTK("   Standard Timings\n");
-	block = edid + STD_TIMING_DESCRIPTIONS_START;
-	for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE) 
-		num += get_std_timing(block, &mode[num]);
-
 	DPRINTK("   Detailed Timings\n");
 	block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
 	for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) {
 	        int first = 1;
 
-		if (block[0] == 0x00 && block[1] == 0x00) {
-			if (block[3] == 0xfa) {
-				num += get_dst_timing(block + 5, &mode[num]);
-			}
-		} else  {
+		if (!(block[0] == 0x00 && block[1] == 0x00)) {
 			get_detailed_timing(block, &mode[num]);
 			if (first) {
 			        mode[num].flag |= FB_MODE_IS_FIRST;
@@ -565,6 +552,21 @@
 			num++;
 		}
 	}
+
+	DPRINTK("   Supported VESA Modes\n");
+	block = edid + ESTABLISHED_TIMING_1;
+	num += get_est_timing(block, &mode[num]);
+
+	DPRINTK("   Standard Timings\n");
+	block = edid + STD_TIMING_DESCRIPTIONS_START;
+	for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE)
+		num += get_std_timing(block, &mode[num]);
+
+	block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+	for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) {
+		if (block[0] == 0x00 && block[1] == 0x00 && block[3] == 0xfa)
+			num += get_dst_timing(block + 5, &mode[num]);
+	}
 	
 	/* Yikes, EDID data is totally useless */
 	if (!num) {
Index: git/drivers/video/i810/i810_main.c
===================================================================
--- git.orig/drivers/video/i810/i810_main.c	2005-10-30 17:09:38.000000000 +0000
+++ git/drivers/video/i810/i810_main.c	2005-10-30 17:11:09.000000000 +0000
@@ -1871,27 +1871,18 @@
 	fb_videomode_to_modelist(specs->modedb, specs->modedb_len,
 				 &info->modelist);
 	if (specs->modedb != NULL) {
-		if (xres && yres) {
-			struct fb_videomode *m;
+		struct fb_videomode *m;
 
+		if (xres && yres) {
 			if ((m = fb_find_best_mode(&var, &info->modelist))) {
 				mode = *m;
 				found  = 1;
 			}
 		}
 
-		if (!found && specs->misc & FB_MISC_1ST_DETAIL) {
-			for (i = 0; i < specs->modedb_len; i++) {
-				if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {
-					mode = specs->modedb[i];
-					found = 1;
-					break;
-				}
-			}
-		}
-
 		if (!found) {
-			mode = specs->modedb[0];
+			m = fb_find_best_display(&info->monspecs, &info->modelist);
+			mode = *m;
 			found = 1;
 		}
 
Index: git/drivers/video/modedb.c
===================================================================
--- git.orig/drivers/video/modedb.c	2005-10-30 17:09:38.000000000 +0000
+++ git/drivers/video/modedb.c	2005-10-30 17:11:09.000000000 +0000
@@ -942,6 +942,66 @@
 	}
 }
 
+struct fb_videomode *fb_find_best_display(struct fb_monspecs *specs,
+					  struct list_head *head)
+{
+	struct list_head *pos;
+	struct fb_modelist *modelist;
+	struct fb_videomode *m, *m1 = NULL, *md = NULL, *best = NULL;
+	int first = 0;
+
+	if (!head->prev || !head->next || list_empty(head))
+		goto finished;
+
+	/* get the first detailed mode and the very first mode */
+	list_for_each(pos, head) {
+		modelist = list_entry(pos, struct fb_modelist, list);
+		m = &modelist->mode;
+
+		if (!first) {
+			m1 = m;
+			first = 1;
+		}
+
+		if (m->flag & FB_MODE_IS_FIRST) {
+ 			md = m;
+			break;
+		}
+	}
+
+	/* first detailed timing is preferred */
+	if (specs->misc & FB_MISC_1ST_DETAIL) {
+		best = md;
+		goto finished;
+	}
+
+	/* find best mode based on display width and height */
+	if (specs->max_x && specs->max_y) {
+		struct fb_var_screeninfo var;
+
+		memset(&var, 0, sizeof(struct fb_var_screeninfo));
+		var.xres = (specs->max_x * 7200)/254;
+		var.yres = (specs->max_y * 7200)/254;
+		m = fb_find_best_mode(&var, head);
+		if (m) {
+			best = m;
+			goto finished;
+		}
+	}
+
+	/* use first detailed mode */
+	if (md) {
+		best = md;
+		goto finished;
+	}
+
+	/* last resort, use the very first mode */
+	best = m1;
+finished:
+	return best;
+}
+EXPORT_SYMBOL(fb_find_best_display);
+
 EXPORT_SYMBOL(fb_videomode_to_var);
 EXPORT_SYMBOL(fb_var_to_videomode);
 EXPORT_SYMBOL(fb_mode_is_equal);
Index: git/drivers/video/nvidia/nvidia.c
===================================================================
--- git.orig/drivers/video/nvidia/nvidia.c	2005-10-30 17:09:38.000000000 +0000
+++ git/drivers/video/nvidia/nvidia.c	2005-10-30 17:11:09.000000000 +0000
@@ -1307,22 +1307,10 @@
 	fb_var_to_videomode(&modedb, &nvidiafb_default_var);
 
 	if (specs->modedb != NULL) {
-		/* get preferred timing */
-		if (specs->misc & FB_MISC_1ST_DETAIL) {
-			int i;
-
-			for (i = 0; i < specs->modedb_len; i++) {
-				if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {
-					modedb = specs->modedb[i];
-					break;
-				}
-			}
-		} else {
-			/* otherwise, get first mode in database */
-			modedb = specs->modedb[0];
-		}
+		struct fb_videomode *modedb;
 
-		fb_videomode_to_var(&nvidiafb_default_var, &modedb);
+		modedb = fb_find_best_display(specs, &info->modelist);
+		fb_videomode_to_var(&nvidiafb_default_var, modedb);
 		nvidiafb_default_var.bits_per_pixel = 8;
 	} else if (par->fpWidth && par->fpHeight) {
 		char buf[16];
Index: git/drivers/video/savage/savagefb_driver.c
===================================================================
--- git.orig/drivers/video/savage/savagefb_driver.c	2005-10-30 17:09:38.000000000 +0000
+++ git/drivers/video/savage/savagefb_driver.c	2005-10-30 17:11:09.000000000 +0000
@@ -2049,24 +2049,11 @@
 			     info->monspecs.modedb, info->monspecs.modedb_len,
 			     NULL, 8);
 	} else if (info->monspecs.modedb != NULL) {
-		struct fb_monspecs *specs = &info->monspecs;
-		struct fb_videomode modedb;
+		struct fb_videomode *modedb;
 
-		if (info->monspecs.misc & FB_MISC_1ST_DETAIL) {
-			int i;
-
-			for (i = 0; i < specs->modedb_len; i++) {
-				if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {
-					modedb = specs->modedb[i];
-					break;
-				}
-			}
-		} else {
-			/* otherwise, get first mode in database */
-			modedb = specs->modedb[0];
-		}
-
-		savage_update_var(&info->var, &modedb);
+		modedb = fb_find_best_display(&info->monspecs,
+					      &info->modelist);
+		savage_update_var(&info->var, modedb);
 	}
 
 	/* maximize virtual vertical length */
Index: git/include/linux/fb.h
===================================================================
--- git.orig/include/linux/fb.h	2005-10-30 17:09:38.000000000 +0000
+++ git/include/linux/fb.h	2005-10-30 17:11:09.000000000 +0000
@@ -903,6 +903,8 @@
 extern void fb_destroy_modelist(struct list_head *head);
 extern void fb_videomode_to_modelist(struct fb_videomode *modedb, int num,
 				     struct list_head *head);
+extern struct fb_videomode *fb_find_best_display(struct fb_monspecs *specs,
+						 struct list_head *head);
 
 /* drivers/video/fbcmap.c */
 extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp);

