diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/video/console/fbcon.c | 42 | ||||
-rw-r--r-- | drivers/video/fbmem.c | 33 |
2 files changed, 75 insertions, 0 deletions
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 6fc3501581d6..34899bd7c9f3 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c | |||
@@ -3043,6 +3043,43 @@ static void fbcon_new_modelist(struct fb_info *info) | |||
3043 | } | 3043 | } |
3044 | } | 3044 | } |
3045 | 3045 | ||
3046 | static void fbcon_get_requirement(struct fb_info *info, | ||
3047 | struct fb_blit_caps *caps) | ||
3048 | { | ||
3049 | struct vc_data *vc; | ||
3050 | struct display *p; | ||
3051 | int charcnt; | ||
3052 | |||
3053 | if (caps->flags) { | ||
3054 | int i; | ||
3055 | |||
3056 | for (i = first_fb_vc; i <= last_fb_vc; i++) { | ||
3057 | vc = vc_cons[i].d; | ||
3058 | if (vc && vc->vc_mode == KD_TEXT) { | ||
3059 | p = &fb_display[i]; | ||
3060 | caps->x |= 1 << (vc->vc_font.width - 1); | ||
3061 | caps->y |= 1 << (vc->vc_font.height - 1); | ||
3062 | charcnt = (p->userfont) ? | ||
3063 | FNTCHARCNT(p->fontdata) : 256; | ||
3064 | if (caps->len < charcnt) | ||
3065 | caps->len = charcnt; | ||
3066 | } | ||
3067 | } | ||
3068 | } else { | ||
3069 | vc = vc_cons[fg_console].d; | ||
3070 | |||
3071 | if (vc && vc->vc_mode == KD_TEXT) { | ||
3072 | p = &fb_display[fg_console]; | ||
3073 | caps->x |= 1 << (vc->vc_font.width - 1); | ||
3074 | caps->y |= 1 << (vc->vc_font.height - 1); | ||
3075 | charcnt = (p->userfont) ? | ||
3076 | FNTCHARCNT(p->fontdata) : 256; | ||
3077 | if (caps->len < charcnt) | ||
3078 | caps->len = charcnt; | ||
3079 | } | ||
3080 | } | ||
3081 | } | ||
3082 | |||
3046 | static int fbcon_event_notify(struct notifier_block *self, | 3083 | static int fbcon_event_notify(struct notifier_block *self, |
3047 | unsigned long action, void *data) | 3084 | unsigned long action, void *data) |
3048 | { | 3085 | { |
@@ -3050,6 +3087,7 @@ static int fbcon_event_notify(struct notifier_block *self, | |||
3050 | struct fb_info *info = event->info; | 3087 | struct fb_info *info = event->info; |
3051 | struct fb_videomode *mode; | 3088 | struct fb_videomode *mode; |
3052 | struct fb_con2fbmap *con2fb; | 3089 | struct fb_con2fbmap *con2fb; |
3090 | struct fb_blit_caps *caps; | ||
3053 | int ret = 0; | 3091 | int ret = 0; |
3054 | 3092 | ||
3055 | /* | 3093 | /* |
@@ -3098,6 +3136,10 @@ static int fbcon_event_notify(struct notifier_block *self, | |||
3098 | case FB_EVENT_NEW_MODELIST: | 3136 | case FB_EVENT_NEW_MODELIST: |
3099 | fbcon_new_modelist(info); | 3137 | fbcon_new_modelist(info); |
3100 | break; | 3138 | break; |
3139 | case FB_EVENT_GET_REQ: | ||
3140 | caps = event->data; | ||
3141 | fbcon_get_requirement(info, caps); | ||
3142 | break; | ||
3101 | } | 3143 | } |
3102 | 3144 | ||
3103 | done: | 3145 | done: |
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index cd1407921af5..354711c84aaa 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c | |||
@@ -773,6 +773,29 @@ fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var) | |||
773 | return 0; | 773 | return 0; |
774 | } | 774 | } |
775 | 775 | ||
776 | static int fb_check_caps(struct fb_info *info, struct fb_var_screeninfo *var, | ||
777 | u32 activate) | ||
778 | { | ||
779 | struct fb_event event; | ||
780 | struct fb_blit_caps caps, fbcaps; | ||
781 | int err = 0; | ||
782 | |||
783 | memset(&caps, 0, sizeof(caps)); | ||
784 | memset(&fbcaps, 0, sizeof(fbcaps)); | ||
785 | caps.flags = (activate & FB_ACTIVATE_ALL) ? 1 : 0; | ||
786 | event.info = info; | ||
787 | event.data = ∩︀ | ||
788 | fb_notifier_call_chain(FB_EVENT_GET_REQ, &event); | ||
789 | info->fbops->fb_get_caps(info, &fbcaps, var); | ||
790 | |||
791 | if (((fbcaps.x ^ caps.x) & caps.x) || | ||
792 | ((fbcaps.y ^ caps.y) & caps.y) || | ||
793 | (fbcaps.len < caps.len)) | ||
794 | err = -EINVAL; | ||
795 | |||
796 | return err; | ||
797 | } | ||
798 | |||
776 | int | 799 | int |
777 | fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) | 800 | fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) |
778 | { | 801 | { |
@@ -817,7 +840,15 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) | |||
817 | struct fb_videomode mode; | 840 | struct fb_videomode mode; |
818 | int err = 0; | 841 | int err = 0; |
819 | 842 | ||
843 | if (info->fbops->fb_get_caps) { | ||
844 | err = fb_check_caps(info, var, activate); | ||
845 | |||
846 | if (err) | ||
847 | goto done; | ||
848 | } | ||
849 | |||
820 | info->var = *var; | 850 | info->var = *var; |
851 | |||
821 | if (info->fbops->fb_set_par) | 852 | if (info->fbops->fb_set_par) |
822 | info->fbops->fb_set_par(info); | 853 | info->fbops->fb_set_par(info); |
823 | 854 | ||
@@ -843,6 +874,8 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) | |||
843 | } | 874 | } |
844 | } | 875 | } |
845 | } | 876 | } |
877 | |||
878 | done: | ||
846 | return 0; | 879 | return 0; |
847 | } | 880 | } |
848 | 881 | ||