Commit 1d0c3774 authored by Antonino Daplas's avatar Antonino Daplas Committed by Linus Torvalds

[PATCH] fbcon/fbdev: Add blanking notification

Add blanking event to the notifier call chain.  This can be used by fbcon
to blank/unblank the console, and theoretically, by backlight drivers.
Signed-off-by: default avatarAntonino Daplas <adaplas@pol.net>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 76ad1ae3
......@@ -2824,7 +2824,7 @@ void do_blank_screen(int entering_gfx)
if (vesa_blank_mode)
sw->con_blank(vc_cons[currcons].d, vesa_blank_mode + 1, 0);
}
EXPORT_SYMBOL(do_blank_screen);
/*
* Called by timer as well as from vt_console_driver
......@@ -2861,6 +2861,7 @@ void do_unblank_screen(int leaving_gfx)
set_palette(currcons);
set_cursor(fg_console);
}
EXPORT_SYMBOL(do_unblank_screen);
/*
* This is called by the outside world to cause a forced unblank, mostly for
......
......@@ -2000,44 +2000,20 @@ static void fbcon_generic_blank(struct vc_data *vc, struct fb_info *info,
int blank)
{
if (blank) {
if (info->fix.visual == FB_VISUAL_DIRECTCOLOR ||
info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {
struct fb_cmap cmap;
u16 *black;
black = kmalloc(sizeof(u16) * info->cmap.len,
GFP_KERNEL);
if (black) {
memset(black, 0, info->cmap.len * sizeof(u16));
cmap.red = cmap.green = cmap.blue = black;
cmap.transp = info->cmap.transp ? black : NULL;
cmap.start = info->cmap.start;
cmap.len = info->cmap.len;
fb_set_cmap(&cmap, info);
}
unsigned short charmask = vc->vc_hi_font_mask ?
0x1ff : 0xff;
unsigned short oldc;
kfree(black);
} else {
unsigned short charmask = vc->vc_hi_font_mask ?
0x1ff : 0xff;
unsigned short oldc;
oldc = vc->vc_video_erase_char;
vc->vc_video_erase_char &= charmask;
fbcon_clear(vc, 0, 0, vc->vc_rows, vc->vc_cols);
vc->vc_video_erase_char = oldc;
}
} else {
if (info->fix.visual == FB_VISUAL_DIRECTCOLOR ||
info->fix.visual == FB_VISUAL_PSEUDOCOLOR)
fb_set_cmap(&info->cmap, info);
oldc = vc->vc_video_erase_char;
vc->vc_video_erase_char &= charmask;
fbcon_clear(vc, 0, 0, vc->vc_rows, vc->vc_cols);
vc->vc_video_erase_char = oldc;
}
}
static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
{
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
struct fbcon_ops *ops = info->fbcon_par;
int active = !fbcon_is_inactive(vc, info);
if (mode_switch) {
......@@ -2061,19 +2037,21 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
}
if (active) {
int ret = -1;
struct fbcon_ops *ops = info->fbcon_par;
fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW);
ops->cursor_flash = (!blank);
if (info->fbops->fb_blank)
ret = info->fbops->fb_blank(blank, info);
if (ops->blank_state != blank) {
if (info->fbops->fb_blank &&
info->fbops->fb_blank(blank, info))
fbcon_generic_blank(vc, info, blank);
if (ret)
fbcon_generic_blank(vc, info, blank);
ops->blank_state = blank;
}
if (!blank)
update_screen(vc->vc_num);
update_screen(vc->vc_num);
}
return 0;
......@@ -2580,14 +2558,12 @@ static void fbcon_modechanged(struct fb_info *info)
struct display *p;
int rows, cols;
if (!ops)
if (!ops || ops->currcon < 0 || vt_cons[ops->currcon]->vc_mode !=
KD_TEXT || registered_fb[con2fb_map[ops->currcon]] != info)
return;
vc = vc_cons[ops->currcon].d;
if (ops->currcon < 0 || vt_cons[ops->currcon]->vc_mode !=
KD_TEXT)
return;
p = &fb_display[vc->vc_num];
info->var.xoffset = info->var.yoffset = p->yscroll = 0;
......@@ -2665,6 +2641,32 @@ static int fbcon_fb_registered(int idx)
return ret;
}
static void fbcon_fb_blanked(struct fb_info *info, int blank)
{
struct fbcon_ops *ops = info->fbcon_par;
int valid = 1;
if (!ops || ops->currcon < 0 ||
vt_cons[ops->currcon]->vc_mode != KD_TEXT ||
registered_fb[con2fb_map[ops->currcon]] != info)
valid = 0;
if (valid) {
struct vc_data *vc;
vc = vc_cons[ops->currcon].d;
if (CON_IS_VISIBLE(vc)) {
ops->blank_state = blank;
if (blank)
do_blank_screen(0);
else
do_unblank_screen(0);
}
}
}
static int fbcon_event_notify(struct notifier_block *self,
unsigned long action, void *data)
{
......@@ -2700,6 +2702,9 @@ static int fbcon_event_notify(struct notifier_block *self,
con2fb = event->data;
con2fb->framebuffer = con2fb_map[con2fb->console - 1];
break;
case FB_EVENT_BLANK:
fbcon_fb_blanked(info, *(int *)event->data);
break;
}
return ret;
......
......@@ -66,6 +66,7 @@ struct fbcon_ops {
int currcon; /* Current VC. */
int cursor_flash;
int cursor_reset;
int blank_state;
char *cursor_data;
};
/*
......
......@@ -730,10 +730,10 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
!list_empty(&info->modelist))
fb_add_videomode(&mode, &info->modelist);
if (info->flags & FBINFO_MISC_MODECHANGEUSER) {
if (info->flags & FBINFO_MISC_USEREVENT) {
struct fb_event event;
info->flags &= ~FBINFO_MISC_MODECHANGEUSER;
info->flags &= ~FBINFO_MISC_USEREVENT;
event.info = info;
notifier_call_chain(&fb_notifier_list,
FB_EVENT_MODE_CHANGE, &event);
......@@ -746,15 +746,23 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
int
fb_blank(struct fb_info *info, int blank)
{
int err = -EINVAL;
int ret = -EINVAL;
if (blank > FB_BLANK_POWERDOWN)
blank = FB_BLANK_POWERDOWN;
if (info->fbops->fb_blank)
err = info->fbops->fb_blank(blank, info);
ret = info->fbops->fb_blank(blank, info);
if (!ret) {
struct fb_event event;
event.info = info;
event.data = &blank;
notifier_call_chain(&fb_notifier_list, FB_EVENT_BLANK, &event);
}
return err;
return ret;
}
static int
......@@ -782,9 +790,9 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
if (copy_from_user(&var, argp, sizeof(var)))
return -EFAULT;
acquire_console_sem();
info->flags |= FBINFO_MISC_MODECHANGEUSER;
info->flags |= FBINFO_MISC_USEREVENT;
i = fb_set_var(info, &var);
info->flags &= ~FBINFO_MISC_MODECHANGEUSER;
info->flags &= ~FBINFO_MISC_USEREVENT;
release_console_sem();
if (i) return i;
if (copy_to_user(argp, &var, sizeof(var)))
......@@ -846,7 +854,9 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
&event);
case FBIOBLANK:
acquire_console_sem();
info->flags |= FBINFO_MISC_USEREVENT;
i = fb_blank(info, arg);
info->flags &= ~FBINFO_MISC_USEREVENT;
release_console_sem();
return i;
default:
......
......@@ -488,7 +488,8 @@ struct fb_cursor_user {
#define FB_EVENT_GET_CONSOLE_MAP 0x06
/* set console to framebuffer mapping */
#define FB_EVENT_SET_CONSOLE_MAP 0x07
/* A display blank is requested */
#define FB_EVENT_BLANK 0x08
struct fb_event {
struct fb_info *info;
......@@ -690,7 +691,7 @@ struct fb_tile_ops {
#define FBINFO_HWACCEL_YPAN 0x2000 /* optional */
#define FBINFO_HWACCEL_YWRAP 0x4000 /* optional */
#define FBINFO_MISC_MODECHANGEUSER 0x10000 /* mode change request
#define FBINFO_MISC_USEREVENT 0x10000 /* event request
from userspace */
#define FBINFO_MISC_MODESWITCH 0x20000 /* mode switch */
#define FBINFO_MISC_MODESWITCHLATE 0x40000 /* init hardware later */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment