Store the display's blank status in struct fb_info.blank and track it in fb_blank(). As an extra, the status is now available from the sysfs blank attribute. Support for blanking is optional. Therefore framebuffer_alloc() initializes the state to FB_BLANK_UNBLANK (i.e., the display is on). If the fb_blank callback has been set, register_framebuffer() sets the state to FB_BLANK_POWERDOWN. On the first modeset, the call to fb_blank() will update it to _UNBLANK. This is important, as listeners to FB_EVENT_BLANK will now see the display being switched on. Signed-off-by: Thomas Zimmermann <tzimmermann@xxxxxxx> --- drivers/video/fbdev/core/fb_info.c | 1 + drivers/video/fbdev/core/fbmem.c | 17 ++++++++++++++++- drivers/video/fbdev/core/fbsysfs.c | 8 ++++---- include/linux/fb.h | 2 ++ 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/drivers/video/fbdev/core/fb_info.c b/drivers/video/fbdev/core/fb_info.c index 4847ebe50d7d..52f9bd2c5417 100644 --- a/drivers/video/fbdev/core/fb_info.c +++ b/drivers/video/fbdev/core/fb_info.c @@ -42,6 +42,7 @@ struct fb_info *framebuffer_alloc(size_t size, struct device *dev) info->device = dev; info->fbcon_rotate_hint = -1; + info->blank = FB_BLANK_UNBLANK; #if IS_ENABLED(CONFIG_FB_BACKLIGHT) mutex_init(&info->bl_curve_mutex); diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index 39e2b81473ad..f34a80c7fc3a 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -341,6 +341,7 @@ EXPORT_SYMBOL(fb_set_var); int fb_blank(struct fb_info *info, int blank) { + int old_blank = info->blank; struct fb_event event; int ret; @@ -353,13 +354,19 @@ int fb_blank(struct fb_info *info, int blank) event.info = info; event.data = ␣ + info->blank = blank; + ret = info->fbops->fb_blank(blank, info); if (ret) - return ret; + goto err; fb_notifier_call_chain(FB_EVENT_BLANK, &event); return 0; + +err: + info->blank = old_blank; + return ret; } EXPORT_SYMBOL(fb_blank); @@ -408,6 +415,14 @@ static int do_register_framebuffer(struct fb_info *fb_info) mutex_init(&fb_info->lock); mutex_init(&fb_info->mm_lock); + /* + * With an fb_blank callback present, we assume that the + * display blank, so that fb_blank() enables it on the first + * modeset. + */ + if (fb_info->fbops->fb_blank) + fb_info->blank = FB_BLANK_POWERDOWN; + fb_device_create(fb_info); if (fb_info->pixmap.addr == NULL) { diff --git a/drivers/video/fbdev/core/fbsysfs.c b/drivers/video/fbdev/core/fbsysfs.c index 1b3c9958ef5c..e337660bce46 100644 --- a/drivers/video/fbdev/core/fbsysfs.c +++ b/drivers/video/fbdev/core/fbsysfs.c @@ -242,11 +242,11 @@ static ssize_t store_blank(struct device *device, return count; } -static ssize_t show_blank(struct device *device, - struct device_attribute *attr, char *buf) +static ssize_t show_blank(struct device *device, struct device_attribute *attr, char *buf) { -// struct fb_info *fb_info = dev_get_drvdata(device); - return 0; + struct fb_info *fb_info = dev_get_drvdata(device); + + return sysfs_emit(buf, "%d\n", fb_info->blank); } static ssize_t store_console(struct device *device, diff --git a/include/linux/fb.h b/include/linux/fb.h index 5ba187e08cf7..f41d3334ac23 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -471,6 +471,8 @@ struct fb_info { struct list_head modelist; /* mode list */ struct fb_videomode *mode; /* current mode */ + int blank; /* current blanking; see FB_BLANK_ constants */ + #if IS_ENABLED(CONFIG_FB_BACKLIGHT) /* assigned backlight device */ /* set before framebuffer registration, -- 2.48.1