fbdev: find mode with the highest/safest refresh rate in fb_find_mode()
authorMichal Januszewski <spock@gentoo.org>
Tue, 16 Oct 2007 08:29:19 +0000 (01:29 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Tue, 16 Oct 2007 16:43:18 +0000 (09:43 -0700)
Currently, if the refresh rate is not specified, fb_find_mode() returns the
first known video mode with the requested resolution, which provides no
guarantees wrt the refresh rate.  Change this so that the mode with the
highest refresh rate is returned when the driver provides a custom video mode
database and the monitor limits, and a mode with the safe 60 Hz refresh rate
otherwise.

Signed-off-by: Michal Januszewski <spock@gentoo.org>
Signed-off-by: Antonino Daplas <adaplas@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
drivers/video/modedb.c

index f7f9c087ad70a96dd645089243fcce1683215e6e..03b06aa2475fdf0bed1e415d11a3f6b94ad71f17 100644 (file)
@@ -606,26 +606,43 @@ done:
        DPRINTK("Trying specified video mode%s %ix%i\n",
            refresh_specified ? "" : " (ignoring refresh rate)", xres, yres);
 
-       diff = refresh;
+       if (!refresh_specified) {
+               /*
+                * If the caller has provided a custom mode database and a
+                * valid monspecs structure, we look for the mode with the
+                * highest refresh rate.  Otherwise we play it safe it and
+                * try to find a mode with a refresh rate closest to the
+                * standard 60 Hz.
+                */
+               if (db != modedb &&
+                   info->monspecs.vfmin && info->monspecs.vfmax &&
+                   info->monspecs.hfmin && info->monspecs.hfmax &&
+                   info->monspecs.dclkmax) {
+                       refresh = 1000;
+               } else {
+                       refresh = 60;
+               }
+       }
+
+       diff = -1;
        best = -1;
        for (i = 0; i < dbsize; i++) {
-               if (name_matches(db[i], name, namelen) ||
-                   (res_specified && res_matches(db[i], xres, yres))) {
-                       if(!fb_try_mode(var, info, &db[i], bpp)) {
-                               if(!refresh_specified || db[i].refresh == refresh)
-                                       return 1;
-                               else {
-                                       if(diff > abs(db[i].refresh - refresh)) {
-                                               diff = abs(db[i].refresh - refresh);
-                                               best = i;
-                                       }
+               if ((name_matches(db[i], name, namelen) ||
+                   (res_specified && res_matches(db[i], xres, yres))) &&
+                   !fb_try_mode(var, info, &db[i], bpp)) {
+                       if (refresh_specified && db[i].refresh == refresh) {
+                               return 1;
+                       } else {
+                               if (abs(db[i].refresh - refresh) < diff) {
+                                       diff = abs(db[i].refresh - refresh);
+                                       best = i;
                                }
                        }
                }
        }
        if (best != -1) {
                fb_try_mode(var, info, &db[best], bpp);
-               return 2;
+               return (refresh_specified) ? 2 : 1;
        }
 
        diff = xres + yres;