From f9e5eb98527feda1937f87d93a5b6dd6322baf83 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Wed, 19 Nov 2008 17:10:58 +0000 Subject: This patch adds a framebuffer notifier in order to detect FB_BLANK events and switch the JBT6K74 LCM controller into its power saving mode. This has the potential of saving something like 50mW during screen blank. Signed-off-by: Harald Welte --- drivers/video/display/jbt6k74.c | 48 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/drivers/video/display/jbt6k74.c b/drivers/video/display/jbt6k74.c index b40629839fc..9570543fc3d 100644 --- a/drivers/video/display/jbt6k74.c +++ b/drivers/video/display/jbt6k74.c @@ -3,6 +3,7 @@ * Copyright (C) 2006-2007 by Openmoko, Inc. * Author: Harald Welte , * Stefan Schmidt + * Copyright (C) 2008 by Harald Welte * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -21,6 +22,7 @@ * MA 02111-1307 USA * */ + #include #include #include @@ -28,6 +30,7 @@ #include #include #include +#include enum jbt_register { JBT_REG_SLEEP_IN = 0x10, @@ -111,6 +114,7 @@ struct jbt_info { enum jbt_state state, last_state; struct spi_device *spi_dev; struct mutex lock; /* protects tx_buf and reg_cache */ + struct notifier_block fb_notif; u16 tx_buf[8]; u16 reg_cache[0xEE]; int have_resumed; @@ -548,6 +552,40 @@ static struct attribute_group jbt_attr_group = { .attrs = jbt_sysfs_entries, }; +static int fb_notifier_callback(struct notifier_block *self, + unsigned long event, void *data) +{ + struct jbt_info *jbt; + struct fb_event *evdata = data; + int fb_blank; + + if (event != FB_EVENT_BLANK && event != FB_EVENT_CONBLANK) + return 0; + + fb_blank = *(int *)evdata->data; + jbt = container_of(self, struct jbt_info, fb_notif); + + switch (fb_blank) { + case FB_BLANK_UNBLANK: + case FB_BLANK_NORMAL: + jbt6k74_enter_state(jbt, JBT_STATE_NORMAL); + jbt6k74_display_onoff(jbt, 1); + break; + case FB_BLANK_VSYNC_SUSPEND: + case FB_BLANK_HSYNC_SUSPEND: + /* FIXME: we disable SLEEP since it would result in + * a visible artefact (white screen) before the backlight + * is dimmed to a dark enough level */ + /* jbt6k74_enter_state(jbt, JBT_STATE_SLEEP); */ + break; + case FB_BLANK_POWERDOWN: + jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY); + break; + } + + return 0; +} + /* linux device model infrastructure */ static int __devinit jbt_probe(struct spi_device *spi) @@ -595,8 +633,17 @@ static int __devinit jbt_probe(struct spi_device *spi) goto err_off; } + jbt->fb_notif.notifier_call = fb_notifier_callback; + rc = fb_register_client(&jbt->fb_notif); + if (rc < 0) { + dev_err(&spi->dev, "cannot register notifier\n"); + goto err_sysfs; + } + return 0; +err_sysfs: + sysfs_remove_group(&spi->dev.kobj, &jbt_attr_group); err_off: jbt6k74_display_onoff(jbt, 0); err_standby: @@ -615,6 +662,7 @@ static int __devexit jbt_remove(struct spi_device *spi) /* We don't want to switch off the display in case the user * accidentially onloads the module (whose use count normally is 0) */ + fb_unregister_client(&jbt->fb_notif); sysfs_remove_group(&spi->dev.kobj, &jbt_attr_group); dev_set_drvdata(&spi->dev, NULL); kfree(jbt); -- cgit v1.2.3