diff options
Diffstat (limited to 'drivers/video/backlight/lcd.c')
-rw-r--r-- | drivers/video/backlight/lcd.c | 108 |
1 files changed, 40 insertions, 68 deletions
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c index 3267acf8dc5b..affe5c52471a 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c @@ -15,86 +15,59 @@ #include <linux/notifier.h> #include <linux/ctype.h> #include <linux/err.h> -#include <linux/fb.h> #include <linux/slab.h> -#if defined(CONFIG_FB) || (defined(CONFIG_FB_MODULE) && \ - defined(CONFIG_LCD_CLASS_DEVICE_MODULE)) -static int to_lcd_power(int fb_blank) -{ - switch (fb_blank) { - case FB_BLANK_UNBLANK: - return LCD_POWER_ON; - /* deprecated; TODO: should become 'off' */ - case FB_BLANK_NORMAL: - return LCD_POWER_REDUCED; - case FB_BLANK_VSYNC_SUSPEND: - return LCD_POWER_REDUCED_VSYNC_SUSPEND; - /* 'off' */ - case FB_BLANK_HSYNC_SUSPEND: - case FB_BLANK_POWERDOWN: - default: - return LCD_POWER_OFF; - } -} +static DEFINE_MUTEX(lcd_dev_list_mutex); +static LIST_HEAD(lcd_dev_list); -/* This callback gets called when something important happens inside a - * framebuffer driver. We're looking if that important event is blanking, - * and if it is, we're switching lcd power as well ... - */ -static int fb_notifier_callback(struct notifier_block *self, - unsigned long event, void *data) +static void lcd_notify_blank(struct lcd_device *ld, struct device *display_dev, + int power) { - struct lcd_device *ld = container_of(self, struct lcd_device, fb_notif); - struct fb_event *evdata = data; - struct fb_info *info = evdata->info; - struct lcd_device *fb_lcd = fb_lcd_device(info); - guard(mutex)(&ld->ops_lock); - if (!ld->ops) - return 0; - if (ld->ops->controls_device && !ld->ops->controls_device(ld, info->device)) - return 0; - if (fb_lcd && fb_lcd != ld) - return 0; + if (!ld->ops || !ld->ops->set_power) + return; + if (ld->ops->controls_device && !ld->ops->controls_device(ld, display_dev)) + return; - if (event == FB_EVENT_BLANK) { - int power = to_lcd_power(*(int *)evdata->data); + ld->ops->set_power(ld, power); +} - if (ld->ops->set_power) - ld->ops->set_power(ld, power); - } else { - const struct fb_videomode *videomode = evdata->data; +void lcd_notify_blank_all(struct device *display_dev, int power) +{ + struct lcd_device *ld; - if (ld->ops->set_mode) - ld->ops->set_mode(ld, videomode->xres, videomode->yres); - } + guard(mutex)(&lcd_dev_list_mutex); - return 0; + list_for_each_entry(ld, &lcd_dev_list, entry) + lcd_notify_blank(ld, display_dev, power); } +EXPORT_SYMBOL(lcd_notify_blank_all); -static int lcd_register_fb(struct lcd_device *ld) +static void lcd_notify_mode_change(struct lcd_device *ld, struct device *display_dev, + unsigned int width, unsigned int height) { - memset(&ld->fb_notif, 0, sizeof(ld->fb_notif)); - ld->fb_notif.notifier_call = fb_notifier_callback; - return fb_register_client(&ld->fb_notif); -} + guard(mutex)(&ld->ops_lock); -static void lcd_unregister_fb(struct lcd_device *ld) -{ - fb_unregister_client(&ld->fb_notif); -} -#else -static int lcd_register_fb(struct lcd_device *ld) -{ - return 0; + if (!ld->ops || !ld->ops->set_mode) + return; + if (ld->ops->controls_device && !ld->ops->controls_device(ld, display_dev)) + return; + + ld->ops->set_mode(ld, width, height); } -static inline void lcd_unregister_fb(struct lcd_device *ld) +void lcd_notify_mode_change_all(struct device *display_dev, + unsigned int width, unsigned int height) { + struct lcd_device *ld; + + guard(mutex)(&lcd_dev_list_mutex); + + list_for_each_entry(ld, &lcd_dev_list, entry) + lcd_notify_mode_change(ld, display_dev, width, height); } -#endif /* CONFIG_FB */ +EXPORT_SYMBOL(lcd_notify_mode_change_all); static ssize_t lcd_power_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -245,11 +218,8 @@ struct lcd_device *lcd_device_register(const char *name, struct device *parent, return ERR_PTR(rc); } - rc = lcd_register_fb(new_ld); - if (rc) { - device_unregister(&new_ld->dev); - return ERR_PTR(rc); - } + guard(mutex)(&lcd_dev_list_mutex); + list_add(&new_ld->entry, &lcd_dev_list); return new_ld; } @@ -266,10 +236,12 @@ void lcd_device_unregister(struct lcd_device *ld) if (!ld) return; + guard(mutex)(&lcd_dev_list_mutex); + list_del(&ld->entry); + mutex_lock(&ld->ops_lock); ld->ops = NULL; mutex_unlock(&ld->ops_lock); - lcd_unregister_fb(ld); device_unregister(&ld->dev); } |