]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
fbdev: Track display blanking state
authorThomas Zimmermann <tzimmermann@suse.de>
Fri, 21 Mar 2025 09:53:55 +0000 (10:53 +0100)
committerLee Jones <lee@kernel.org>
Thu, 10 Apr 2025 09:38:57 +0000 (10:38 +0100)
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@suse.de>
Acked-by: Simona Vetter <simona.vetter@ffwll.ch>
Link: https://lore.kernel.org/r/20250321095517.313713-3-tzimmermann@suse.de
Signed-off-by: Lee Jones <lee@kernel.org>
drivers/video/fbdev/core/fb_info.c
drivers/video/fbdev/core/fbmem.c
drivers/video/fbdev/core/fbsysfs.c
include/linux/fb.h

index 4847ebe50d7d7a9738ddc4e32721596d0107800b..52f9bd2c5417afeac815654837aee2d2c002b158 100644 (file)
@@ -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);
index 39e2b81473ad0d9abfa021e3f1686b1afe8f706d..5d1529d300b757167206e29816611aadc4752afd 100644 (file)
@@ -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 = &blank;
 
+       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 is 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) {
index 06d75c76757942191d79777b1188a1a8740fc92d..b8344c40073b4177a88fe21296fdaeb9120bc8aa 100644 (file)
@@ -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,
index cd653862ab99818c3c64c9435616209b089cf02f..348aa2e146e2afd70fed3f809c42f0afd75e7479 100644 (file)
@@ -472,6 +472,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,