diff options
author | Harald Welte <laforge@openmoko.org> | 2008-11-19 17:10:58 +0000 |
---|---|---|
committer | Andy Green <agreen@pads.home.warmcat.com> | 2008-11-19 17:10:58 +0000 |
commit | f9e5eb98527feda1937f87d93a5b6dd6322baf83 (patch) | |
tree | 75b817f369d279d34edd6d27c43d6ac1094bd4c4 | |
parent | 0e7b63e010904140cc39fe98a5d8abd3de7e4f0f (diff) |
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 <laforge@openmoko.org>
-rw-r--r-- | drivers/video/display/jbt6k74.c | 48 |
1 files changed, 48 insertions, 0 deletions
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 <laforge@openmoko.org>, * Stefan Schmidt <stefan@openmoko.org> + * Copyright (C) 2008 by Harald Welte <laforge@openmoko.org> * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -21,6 +22,7 @@ * MA 02111-1307 USA * */ + #include <linux/kernel.h> #include <linux/types.h> #include <linux/module.h> @@ -28,6 +30,7 @@ #include <linux/platform_device.h> #include <linux/delay.h> #include <linux/jbt6k74.h> +#include <linux/fb.h> 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); |