backlight: Match backlight device against struct fb_info.bl_dev
authorThomas Zimmermann <tzimmermann@suse.de>
Tue, 5 Mar 2024 16:22:34 +0000 (17:22 +0100)
committerLee Jones <lee@kernel.org>
Thu, 28 Mar 2024 10:08:47 +0000 (10:08 +0000)
Framebuffer drivers for devices with dedicated backlight are supposed
to set struct fb_info.bl_dev to the backlight's respective device. Use
the value to match backlight and framebuffer in the backlight core code.

The code first tests against struct backlight_ops.check_ops. If this
test succeeds, it performs the test against fbdev. So backlight drivers
can override the later test as before.

Fbdev's backlight support depends on CONFIG_FB_BACKLIGHT. To avoid
ifdef in the code, the new helper fb_bl_device() returns the backlight
device, or NULL if the config option has been disabled. The test in
the backlight code will then do nothing.

v4:
* declare empty fb_bl_device() as static inline
* export fb_bl_device()
v3:
* hide ifdef in fb_bl_device() (Lee)
* no if-else blocks (Andy)

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Daniel Thompson <daniel.thompson@linaro.org>
Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
Link: https://lore.kernel.org/r/20240305162425.23845-2-tzimmermann@suse.de
Signed-off-by: Lee Jones <lee@kernel.org>
drivers/video/backlight/backlight.c
drivers/video/fbdev/core/fb_backlight.c
include/linux/fb.h

index 86e1cdc8e369774a9010178e48ca6c90e0458119..4f7973c6fcc798dbf6fe9319fa48e1da744fc07f 100644 (file)
@@ -98,7 +98,9 @@ static int fb_notifier_callback(struct notifier_block *self,
 {
        struct backlight_device *bd;
        struct fb_event *evdata = data;
-       int node = evdata->info->node;
+       struct fb_info *info = evdata->info;
+       struct backlight_device *fb_bd = fb_bl_device(info);
+       int node = info->node;
        int fb_blank = 0;
 
        /* If we aren't interested in this event, skip it immediately ... */
@@ -110,7 +112,9 @@ static int fb_notifier_callback(struct notifier_block *self,
 
        if (!bd->ops)
                goto out;
-       if (bd->ops->check_fb && !bd->ops->check_fb(bd, evdata->info))
+       if (bd->ops->check_fb && !bd->ops->check_fb(bd, info))
+               goto out;
+       if (fb_bd && fb_bd != bd)
                goto out;
 
        fb_blank = *(int *)evdata->data;
index e2d3b3adc870f7164cd3c91421ce92e06438bc15..6fdaa9f81be90c413868bdd8f10d025bbb6a8ecd 100644 (file)
@@ -30,4 +30,10 @@ void fb_bl_default_curve(struct fb_info *fb_info, u8 off, u8 min, u8 max)
        mutex_unlock(&fb_info->bl_curve_mutex);
 }
 EXPORT_SYMBOL_GPL(fb_bl_default_curve);
+
+struct backlight_device *fb_bl_device(struct fb_info *info)
+{
+       return info->bl_dev;
+}
+EXPORT_SYMBOL(fb_bl_device);
 #endif
index 0dd27364d56fe04e7a72bc3319ff4c8790cb2282..75c5f800467c712ad3a216f776fa69dc103c356e 100644 (file)
@@ -738,6 +738,15 @@ extern struct fb_info *framebuffer_alloc(size_t size, struct device *dev);
 extern void framebuffer_release(struct fb_info *info);
 extern void fb_bl_default_curve(struct fb_info *fb_info, u8 off, u8 min, u8 max);
 
+#if IS_ENABLED(CONFIG_FB_BACKLIGHT)
+struct backlight_device *fb_bl_device(struct fb_info *info);
+#else
+static inline struct backlight_device *fb_bl_device(struct fb_info *info)
+{
+       return NULL;
+}
+#endif
+
 /* fbmon.c */
 #define FB_MAXTIMINGS          0
 #define FB_VSYNCTIMINGS                1