diff options
-rw-r--r-- | drivers/video/console/fbcon.c | 42 | ||||
-rw-r--r-- | drivers/video/fbmem.c | 33 | ||||
-rw-r--r-- | include/linux/fb.h | 12 |
3 files changed, 87 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 | ||
diff --git a/include/linux/fb.h b/include/linux/fb.h index a2f382c01cd2..dff7a728948c 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h | |||
@@ -527,12 +527,20 @@ struct fb_cursor_user { | |||
527 | #define FB_EVENT_MODE_CHANGE_ALL 0x0B | 527 | #define FB_EVENT_MODE_CHANGE_ALL 0x0B |
528 | /* A software display blank change occured */ | 528 | /* A software display blank change occured */ |
529 | #define FB_EVENT_CONBLANK 0x0C | 529 | #define FB_EVENT_CONBLANK 0x0C |
530 | /* Get drawing requirements */ | ||
531 | #define FB_EVENT_GET_REQ 0x0D | ||
530 | 532 | ||
531 | struct fb_event { | 533 | struct fb_event { |
532 | struct fb_info *info; | 534 | struct fb_info *info; |
533 | void *data; | 535 | void *data; |
534 | }; | 536 | }; |
535 | 537 | ||
538 | struct fb_blit_caps { | ||
539 | u32 x; | ||
540 | u32 y; | ||
541 | u32 len; | ||
542 | u32 flags; | ||
543 | }; | ||
536 | 544 | ||
537 | extern int fb_register_client(struct notifier_block *nb); | 545 | extern int fb_register_client(struct notifier_block *nb); |
538 | extern int fb_unregister_client(struct notifier_block *nb); | 546 | extern int fb_unregister_client(struct notifier_block *nb); |
@@ -652,6 +660,10 @@ struct fb_ops { | |||
652 | 660 | ||
653 | /* restore saved state */ | 661 | /* restore saved state */ |
654 | void (*fb_restore_state)(struct fb_info *info); | 662 | void (*fb_restore_state)(struct fb_info *info); |
663 | |||
664 | /* get capability given var */ | ||
665 | void (*fb_get_caps)(struct fb_info *info, struct fb_blit_caps *caps, | ||
666 | struct fb_var_screeninfo *var); | ||
655 | }; | 667 | }; |
656 | 668 | ||
657 | #ifdef CONFIG_FB_TILEBLITTING | 669 | #ifdef CONFIG_FB_TILEBLITTING |