aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/video/console/fbcon.c42
-rw-r--r--drivers/video/fbmem.c33
-rw-r--r--include/linux/fb.h12
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
3046static 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
3046static int fbcon_event_notify(struct notifier_block *self, 3083static 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
3103done: 3145done:
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
776static 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 = &caps;
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
776int 799int
777fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) 800fb_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
531struct fb_event { 533struct fb_event {
532 struct fb_info *info; 534 struct fb_info *info;
533 void *data; 535 void *data;
534}; 536};
535 537
538struct fb_blit_caps {
539 u32 x;
540 u32 y;
541 u32 len;
542 u32 flags;
543};
536 544
537extern int fb_register_client(struct notifier_block *nb); 545extern int fb_register_client(struct notifier_block *nb);
538extern int fb_unregister_client(struct notifier_block *nb); 546extern 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