diff options
Diffstat (limited to 'drivers/video/modedb.c')
-rw-r--r-- | drivers/video/modedb.c | 84 |
1 files changed, 73 insertions, 11 deletions
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c index 47516c44a390..1789a52d776a 100644 --- a/drivers/video/modedb.c +++ b/drivers/video/modedb.c | |||
@@ -676,6 +676,8 @@ void fb_var_to_videomode(struct fb_videomode *mode, | |||
676 | mode->sync = var->sync; | 676 | mode->sync = var->sync; |
677 | mode->vmode = var->vmode & FB_VMODE_MASK; | 677 | mode->vmode = var->vmode & FB_VMODE_MASK; |
678 | mode->flag = FB_MODE_IS_FROM_VAR; | 678 | mode->flag = FB_MODE_IS_FROM_VAR; |
679 | mode->refresh = 0; | ||
680 | |||
679 | if (!var->pixclock) | 681 | if (!var->pixclock) |
680 | return; | 682 | return; |
681 | 683 | ||
@@ -785,39 +787,39 @@ struct fb_videomode *fb_find_best_mode(struct fb_var_screeninfo *var, | |||
785 | } | 787 | } |
786 | 788 | ||
787 | /** | 789 | /** |
788 | * fb_find_nearest_mode - find mode closest video mode | 790 | * fb_find_nearest_mode - find closest videomode |
789 | * | 791 | * |
790 | * @var: pointer to struct fb_var_screeninfo | 792 | * @mode: pointer to struct fb_videomode |
791 | * @head: pointer to modelist | 793 | * @head: pointer to modelist |
792 | * | 794 | * |
793 | * Finds best matching videomode, smaller or greater in dimension. | 795 | * Finds best matching videomode, smaller or greater in dimension. |
794 | * If more than 1 videomode is found, will return the videomode with | 796 | * If more than 1 videomode is found, will return the videomode with |
795 | * the closest refresh rate | 797 | * the closest refresh rate. |
796 | */ | 798 | */ |
797 | struct fb_videomode *fb_find_nearest_mode(struct fb_var_screeninfo *var, | 799 | struct fb_videomode *fb_find_nearest_mode(struct fb_videomode *mode, |
798 | struct list_head *head) | 800 | struct list_head *head) |
799 | { | 801 | { |
800 | struct list_head *pos; | 802 | struct list_head *pos; |
801 | struct fb_modelist *modelist; | 803 | struct fb_modelist *modelist; |
802 | struct fb_videomode *mode, *best = NULL; | 804 | struct fb_videomode *cmode, *best = NULL; |
803 | u32 diff = -1, diff_refresh = -1; | 805 | u32 diff = -1, diff_refresh = -1; |
804 | 806 | ||
805 | list_for_each(pos, head) { | 807 | list_for_each(pos, head) { |
806 | u32 d; | 808 | u32 d; |
807 | 809 | ||
808 | modelist = list_entry(pos, struct fb_modelist, list); | 810 | modelist = list_entry(pos, struct fb_modelist, list); |
809 | mode = &modelist->mode; | 811 | cmode = &modelist->mode; |
810 | 812 | ||
811 | d = abs(mode->xres - var->xres) + | 813 | d = abs(cmode->xres - mode->xres) + |
812 | abs(mode->yres - var->yres); | 814 | abs(cmode->yres - mode->yres); |
813 | if (diff > d) { | 815 | if (diff > d) { |
814 | diff = d; | 816 | diff = d; |
815 | best = mode; | 817 | best = cmode; |
816 | } else if (diff == d) { | 818 | } else if (diff == d) { |
817 | d = abs(mode->refresh - best->refresh); | 819 | d = abs(cmode->refresh - mode->refresh); |
818 | if (diff_refresh > d) { | 820 | if (diff_refresh > d) { |
819 | diff_refresh = d; | 821 | diff_refresh = d; |
820 | best = mode; | 822 | best = cmode; |
821 | } | 823 | } |
822 | } | 824 | } |
823 | } | 825 | } |
@@ -942,6 +944,66 @@ void fb_videomode_to_modelist(struct fb_videomode *modedb, int num, | |||
942 | } | 944 | } |
943 | } | 945 | } |
944 | 946 | ||
947 | struct fb_videomode *fb_find_best_display(struct fb_monspecs *specs, | ||
948 | struct list_head *head) | ||
949 | { | ||
950 | struct list_head *pos; | ||
951 | struct fb_modelist *modelist; | ||
952 | struct fb_videomode *m, *m1 = NULL, *md = NULL, *best = NULL; | ||
953 | int first = 0; | ||
954 | |||
955 | if (!head->prev || !head->next || list_empty(head)) | ||
956 | goto finished; | ||
957 | |||
958 | /* get the first detailed mode and the very first mode */ | ||
959 | list_for_each(pos, head) { | ||
960 | modelist = list_entry(pos, struct fb_modelist, list); | ||
961 | m = &modelist->mode; | ||
962 | |||
963 | if (!first) { | ||
964 | m1 = m; | ||
965 | first = 1; | ||
966 | } | ||
967 | |||
968 | if (m->flag & FB_MODE_IS_FIRST) { | ||
969 | md = m; | ||
970 | break; | ||
971 | } | ||
972 | } | ||
973 | |||
974 | /* first detailed timing is preferred */ | ||
975 | if (specs->misc & FB_MISC_1ST_DETAIL) { | ||
976 | best = md; | ||
977 | goto finished; | ||
978 | } | ||
979 | |||
980 | /* find best mode based on display width and height */ | ||
981 | if (specs->max_x && specs->max_y) { | ||
982 | struct fb_var_screeninfo var; | ||
983 | |||
984 | memset(&var, 0, sizeof(struct fb_var_screeninfo)); | ||
985 | var.xres = (specs->max_x * 7200)/254; | ||
986 | var.yres = (specs->max_y * 7200)/254; | ||
987 | m = fb_find_best_mode(&var, head); | ||
988 | if (m) { | ||
989 | best = m; | ||
990 | goto finished; | ||
991 | } | ||
992 | } | ||
993 | |||
994 | /* use first detailed mode */ | ||
995 | if (md) { | ||
996 | best = md; | ||
997 | goto finished; | ||
998 | } | ||
999 | |||
1000 | /* last resort, use the very first mode */ | ||
1001 | best = m1; | ||
1002 | finished: | ||
1003 | return best; | ||
1004 | } | ||
1005 | EXPORT_SYMBOL(fb_find_best_display); | ||
1006 | |||
945 | EXPORT_SYMBOL(fb_videomode_to_var); | 1007 | EXPORT_SYMBOL(fb_videomode_to_var); |
946 | EXPORT_SYMBOL(fb_var_to_videomode); | 1008 | EXPORT_SYMBOL(fb_var_to_videomode); |
947 | EXPORT_SYMBOL(fb_mode_is_equal); | 1009 | EXPORT_SYMBOL(fb_mode_is_equal); |