summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Morton <akpm@osdl.org>2004-06-23 19:21:13 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-06-23 19:21:13 -0700
commit81d5fd846719a74a43ec5497ed469f88fb11cd85 (patch)
tree4f641c39c4140e2bafabd0eccd463afe889e3ef4
parent0a88d6091a146d1a25f3736f40c5d017a301f487 (diff)
[PATCH] fbdev: video mode change notify (fbset)
From: "Antonino A. Daplas" <adaplas@hotpop.com> This patch allows fbset to change the video mode and the console window size via the notifier call chain. It will only notify fbcon of mode changes from user space. Changes coming from upstream will be ignored. The code will only update the current console. Signed-off-by: Antonino Daplas <adaplas@pol.net> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--drivers/video/console/fbcon.c53
-rw-r--r--drivers/video/fbmem.c8
-rw-r--r--include/linux/fb.h2
3 files changed, 62 insertions, 1 deletions
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index f25e11b649ff..58a9b8a8b722 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -2358,6 +2358,56 @@ static void fbcon_resumed(struct fb_info *info)
update_screen(vc->vc_num);
}
+static void fbcon_modechanged(struct fb_info *info)
+{
+ struct vc_data *vc = vc_cons[info->currcon].d;
+ struct display *p;
+ int rows, cols;
+
+ if (info->currcon < 0 || vt_cons[info->currcon]->vc_mode !=
+ KD_TEXT)
+ return;
+ p = &fb_display[vc->vc_num];
+
+ info->var.xoffset = info->var.yoffset = p->yscroll = 0;
+ vc->vc_can_do_color = info->var.bits_per_pixel != 1;
+ vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
+
+ if (CON_IS_VISIBLE(vc)) {
+ cols = info->var.xres / vc->vc_font.width;
+ rows = info->var.yres / vc->vc_font.height;
+ vc_resize(vc->vc_num, cols, rows);
+ switch (p->scrollmode) {
+ case SCROLL_WRAP:
+ scrollback_phys_max = p->vrows - vc->vc_rows;
+ break;
+ case SCROLL_PAN:
+ scrollback_phys_max = p->vrows - 2 * vc->vc_rows;
+ if (scrollback_phys_max < 0)
+ scrollback_phys_max = 0;
+ break;
+ default:
+ scrollback_phys_max = 0;
+ break;
+ }
+ scrollback_max = 0;
+ scrollback_current = 0;
+ update_var(vc->vc_num, info);
+ fbcon_set_palette(vc, color_table);
+ update_screen(vc->vc_num);
+ if (softback_buf) {
+ int l = fbcon_softback_size / vc->vc_size_row;
+ if (l > 5)
+ softback_end = softback_buf + l * vc->vc_size_row;
+ else {
+ /* Smaller scrollback makes no sense, and 0
+ would screw the operation totally */
+ softback_top = 0;
+ }
+ }
+ }
+}
+
static int fbcon_event_notify(struct notifier_block *self,
unsigned long action, void *data)
{
@@ -2370,6 +2420,9 @@ static int fbcon_event_notify(struct notifier_block *self,
case FB_EVENT_RESUME:
fbcon_resumed(info);
break;
+ case FB_EVENT_MODE_CHANGE:
+ fbcon_modechanged(info);
+ break;
}
return 0;
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 6162b5ab7c67..bbdd131dbb34 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1005,7 +1005,11 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
fb_set_cmap(&info->cmap, 1, info);
- notifier_call_chain(&fb_notifier_list, FB_EVENT_MODE_CHANGE, info);
+ if (info->flags & FBINFO_MISC_MODECHANGEUSER) {
+ notifier_call_chain(&fb_notifier_list,
+ FB_EVENT_MODE_CHANGE, info);
+ info->flags &= ~FBINFO_MISC_MODECHANGEUSER;
+ }
}
}
return 0;
@@ -1056,7 +1060,9 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
if (copy_from_user(&var, (void *) arg, sizeof(var)))
return -EFAULT;
acquire_console_sem();
+ info->flags |= FBINFO_MISC_MODECHANGEUSER;
i = fb_set_var(info, &var);
+ info->flags &= ~FBINFO_MISC_MODECHANGEUSER;
release_console_sem();
if (i) return i;
if (copy_to_user((void *) arg, &var, sizeof(var)))
diff --git a/include/linux/fb.h b/include/linux/fb.h
index c2ff4024cc25..a25a0ae12656 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -530,6 +530,8 @@ struct fb_ops {
#define FBINFO_HWACCEL_YPAN 0x2000 /* optional */
#define FBINFO_HWACCEL_YWRAP 0x4000 /* optional */
+#define FBINFO_MISC_MODECHANGEUSER 0x10000 /* mode change request
+ from userspace */
struct fb_info {
int node;