diff options
author | Michal Januszewski <spock@gentoo.org> | 2008-04-28 05:14:48 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-28 11:58:35 -0400 |
commit | 6b745b6fd02213f4b2fef2f2635985929fc5b8cc (patch) | |
tree | 4be3db651080c3008862b8b3604b2c1231a55c27 | |
parent | 169b6a7a6e91e1ea32136681b475cbaf2074bf35 (diff) |
fbdev: make the best-fit section of fb_find_mode return the closest matching mode
Currently, if a perfect match in terms of resolution is not found,
fb_find_mode() only looks for a best-fit mode among modes with a higher
resolution than the one requested. Thus, if the user requests a resolution
higher than the largest supported one, they are dropped to the default mode
(usually a low resolution one).
Change this behaviour so that all valid video modes are considered when
looking for a best-fit mode, while still preferring modes with a higher
resolution.
Signed-off-by: Michal Januszewski <spock@gentoo.org>
Cc: Krzysztof Helt <krzysztof.h1@poczta.fm>
Cc: "Antonino A. Daplas" <adaplas@pol.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | drivers/video/modedb.c | 24 |
1 files changed, 16 insertions, 8 deletions
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c index 08d072552233..640351c9a9e1 100644 --- a/drivers/video/modedb.c +++ b/drivers/video/modedb.c | |||
@@ -522,7 +522,7 @@ int fb_find_mode(struct fb_var_screeninfo *var, | |||
522 | int res_specified = 0, bpp_specified = 0, refresh_specified = 0; | 522 | int res_specified = 0, bpp_specified = 0, refresh_specified = 0; |
523 | unsigned int xres = 0, yres = 0, bpp = default_bpp, refresh = 0; | 523 | unsigned int xres = 0, yres = 0, bpp = default_bpp, refresh = 0; |
524 | int yres_specified = 0, cvt = 0, rb = 0, interlace = 0, margins = 0; | 524 | int yres_specified = 0, cvt = 0, rb = 0, interlace = 0, margins = 0; |
525 | u32 best, diff; | 525 | u32 best, diff, tdiff; |
526 | 526 | ||
527 | for (i = namelen-1; i >= 0; i--) { | 527 | for (i = namelen-1; i >= 0; i--) { |
528 | switch (name[i]) { | 528 | switch (name[i]) { |
@@ -651,19 +651,27 @@ done: | |||
651 | return (refresh_specified) ? 2 : 1; | 651 | return (refresh_specified) ? 2 : 1; |
652 | } | 652 | } |
653 | 653 | ||
654 | diff = xres + yres; | 654 | diff = 2 * (xres + yres); |
655 | best = -1; | 655 | best = -1; |
656 | DPRINTK("Trying best-fit modes\n"); | 656 | DPRINTK("Trying best-fit modes\n"); |
657 | for (i = 0; i < dbsize; i++) { | 657 | for (i = 0; i < dbsize; i++) { |
658 | if (xres <= db[i].xres && yres <= db[i].yres) { | ||
659 | DPRINTK("Trying %ix%i\n", db[i].xres, db[i].yres); | 658 | DPRINTK("Trying %ix%i\n", db[i].xres, db[i].yres); |
660 | if (!fb_try_mode(var, info, &db[i], bpp)) { | 659 | if (!fb_try_mode(var, info, &db[i], bpp)) { |
661 | if (diff > (db[i].xres - xres) + (db[i].yres - yres)) { | 660 | tdiff = abs(db[i].xres - xres) + |
662 | diff = (db[i].xres - xres) + (db[i].yres - yres); | 661 | abs(db[i].yres - yres); |
663 | best = i; | 662 | |
664 | } | 663 | /* |
664 | * Penalize modes with resolutions smaller | ||
665 | * than requested. | ||
666 | */ | ||
667 | if (xres > db[i].xres || yres > db[i].yres) | ||
668 | tdiff += xres + yres; | ||
669 | |||
670 | if (diff > tdiff) { | ||
671 | diff = tdiff; | ||
672 | best = i; | ||
673 | } | ||
665 | } | 674 | } |
666 | } | ||
667 | } | 675 | } |
668 | if (best != -1) { | 676 | if (best != -1) { |
669 | fb_try_mode(var, info, &db[best], bpp); | 677 | fb_try_mode(var, info, &db[best], bpp); |