summaryrefslogtreecommitdiffstats
path: root/drivers/video/fbmem.c
diff options
context:
space:
mode:
authorAntonino A. Daplas <adaplas@gmail.com>2007-05-08 09:39:37 +0200
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-08 20:15:32 +0200
commit38a3dc51852d8350b156ea909c5aa8767d71b005 (patch)
tree933e9a4b7b0a0d871aaccd7d44e9224ea6c4a0b5 /drivers/video/fbmem.c
parentnvidiafb: prevent triggering of softlockup (diff)
downloadlinux-38a3dc51852d8350b156ea909c5aa8767d71b005.tar.xz
linux-38a3dc51852d8350b156ea909c5aa8767d71b005.zip
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/video/fbmem.c')
-rw-r--r--drivers/video/fbmem.c33
1 files changed, 33 insertions, 0 deletions
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)
return 0;
}
+static int fb_check_caps(struct fb_info *info, struct fb_var_screeninfo *var,
+ u32 activate)
+{
+ struct fb_event event;
+ struct fb_blit_caps caps, fbcaps;
+ int err = 0;
+
+ memset(&caps, 0, sizeof(caps));
+ memset(&fbcaps, 0, sizeof(fbcaps));
+ caps.flags = (activate & FB_ACTIVATE_ALL) ? 1 : 0;
+ event.info = info;
+ event.data = &caps;
+ fb_notifier_call_chain(FB_EVENT_GET_REQ, &event);
+ info->fbops->fb_get_caps(info, &fbcaps, var);
+
+ if (((fbcaps.x ^ caps.x) & caps.x) ||
+ ((fbcaps.y ^ caps.y) & caps.y) ||
+ (fbcaps.len < caps.len))
+ err = -EINVAL;
+
+ return err;
+}
+
int
fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
{
@@ -817,7 +840,15 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
struct fb_videomode mode;
int err = 0;
+ if (info->fbops->fb_get_caps) {
+ err = fb_check_caps(info, var, activate);
+
+ if (err)
+ goto done;
+ }
+
info->var = *var;
+
if (info->fbops->fb_set_par)
info->fbops->fb_set_par(info);
@@ -843,6 +874,8 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
}
}
}
+
+ done:
return 0;
}