aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAntonino A. Daplas <adaplas@gmail.com>2007-05-08 03:39:37 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-08 14:15:32 -0400
commit38a3dc51852d8350b156ea909c5aa8767d71b005 (patch)
tree933e9a4b7b0a0d871aaccd7d44e9224ea6c4a0b5 /drivers
parente15de77e74d429f14641ebe7a29ccd8aa6656f3c (diff)
fbdev: fbcon: check if mode can handle new screen
Check if the mode can properly display the screen. This will be needed by drivers where the capability is not constant with each mode. The function fb_set_var() will query fbcon the requirement, then it will query the driver (via a new hook fb_get_caps()) its capability. If the driver's capability cannot handle fbcon's requirement, then fb_set_var() will fail. For example, if a particular driver supports 2 modes where: mode1 = can only display 8x16 bitmaps mode2 = can display any bitmap then if current mode = mode2 and current font = 12x22 fbset <mode1> /* mode1 cannot handle 12x22 */ fbset will fail Signed-off-by: Antonino Daplas <adaplas@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/video/console/fbcon.c42
-rw-r--r--drivers/video/fbmem.c33
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
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