diff options
Diffstat (limited to 'drivers/video/backlight/lcd.c')
-rw-r--r-- | drivers/video/backlight/lcd.c | 50 |
1 files changed, 38 insertions, 12 deletions
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c index ceec90ca758b..3267acf8dc5b 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c @@ -20,6 +20,24 @@ #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; + } +} + /* 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 ... @@ -27,24 +45,32 @@ static int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data) { - struct lcd_device *ld; + 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); - ld = container_of(self, struct lcd_device, fb_notif); 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; - mutex_lock(&ld->ops_lock); - if (!ld->ops->check_fb || ld->ops->check_fb(ld, evdata->info)) { - if (event == FB_EVENT_BLANK) { - if (ld->ops->set_power) - ld->ops->set_power(ld, *(int *)evdata->data); - } else { - if (ld->ops->set_mode) - ld->ops->set_mode(ld, evdata->data); - } + if (event == FB_EVENT_BLANK) { + int power = to_lcd_power(*(int *)evdata->data); + + if (ld->ops->set_power) + ld->ops->set_power(ld, power); + } else { + const struct fb_videomode *videomode = evdata->data; + + if (ld->ops->set_mode) + ld->ops->set_mode(ld, videomode->xres, videomode->yres); } - mutex_unlock(&ld->ops_lock); + return 0; } |