mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2024-11-25 05:24:59 +02:00
270 lines
9.3 KiB
Diff
270 lines
9.3 KiB
Diff
|
From 36b19597a232bb198b3bab4003c0f0807c821274 Mon Sep 17 00:00:00 2001
|
||
|
From: Andy Green <andy@openmoko.com>
|
||
|
Date: Fri, 25 Jul 2008 23:06:08 +0100
|
||
|
Subject: [PATCH] fix-suspend-backlight-timing-pm-debug.patch
|
||
|
|
||
|
This patch improves the smoothness of suspend and resume action.
|
||
|
|
||
|
Taking out CONFIG_PM_DEBUG allows much more rapid resume (the low level
|
||
|
serial traffic appears to be synchronous)
|
||
|
|
||
|
Added a platform callback in jbt driver and support in pcf50633 so we
|
||
|
can defer bringing up the backlight until the LCM is able to process
|
||
|
video again (which must happen after the glamo is up and producing
|
||
|
video beacuse the LCM is hooked to glamo SPI)
|
||
|
|
||
|
GTA01 should not be affected by all this as the callback will default
|
||
|
to null and it is on pcf50606
|
||
|
|
||
|
Signed-off-by: Andy Green <andy@openmoko.com>
|
||
|
---
|
||
|
arch/arm/mach-s3c2440/mach-gta02.c | 8 ++++++
|
||
|
defconfig-2.6.24 | 4 +-
|
||
|
drivers/i2c/chips/pcf50633.c | 50 ++++++++++++++++++++++++++---------
|
||
|
drivers/video/display/jbt6k74.c | 12 ++++++++-
|
||
|
include/linux/jbt6k74.h | 3 +-
|
||
|
include/linux/pcf50633.h | 6 ++++
|
||
|
6 files changed, 66 insertions(+), 17 deletions(-)
|
||
|
|
||
|
diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
|
||
|
index 1954121..e1984a9 100644
|
||
|
--- a/arch/arm/mach-s3c2440/mach-gta02.c
|
||
|
+++ b/arch/arm/mach-s3c2440/mach-gta02.c
|
||
|
@@ -532,6 +532,7 @@ static struct pcf50633_platform_data gta02_pcf_pdata = {
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
+ .defer_resume_backlight = 1,
|
||
|
};
|
||
|
|
||
|
#if 0 /* currently unused */
|
||
|
@@ -828,9 +829,16 @@ void gta02_jbt6k74_reset(int devidx, int level)
|
||
|
glamo_lcm_reset(level);
|
||
|
}
|
||
|
|
||
|
+/* finally bring up deferred backlight resume now LCM is resumed itself */
|
||
|
+
|
||
|
+void gta02_jbt6k74_resuming(int devidx)
|
||
|
+{
|
||
|
+ pcf50633_backlight_resume(pcf50633_global);
|
||
|
+}
|
||
|
|
||
|
const struct jbt6k74_platform_data jbt6k74_pdata = {
|
||
|
.reset = gta02_jbt6k74_reset,
|
||
|
+ .resuming = gta02_jbt6k74_resuming,
|
||
|
};
|
||
|
|
||
|
static struct spi_board_info gta02_spi_board_info[] = {
|
||
|
diff --git a/defconfig-2.6.24 b/defconfig-2.6.24
|
||
|
index 4df10bf..34fa961 100644
|
||
|
--- a/defconfig-2.6.24
|
||
|
+++ b/defconfig-2.6.24
|
||
|
@@ -161,7 +161,7 @@ CONFIG_CPU_LLSERIAL_S3C2440=y
|
||
|
#
|
||
|
# Power management
|
||
|
#
|
||
|
-CONFIG_S3C2410_PM_DEBUG=y
|
||
|
+# CONFIG_S3C2410_PM_DEBUG is not set
|
||
|
# CONFIG_S3C2410_PM_CHECK is not set
|
||
|
CONFIG_S3C_LOWLEVEL_UART_PORT=2
|
||
|
|
||
|
@@ -1754,7 +1754,7 @@ CONFIG_FORCED_INLINING=y
|
||
|
# CONFIG_SAMPLES is not set
|
||
|
# CONFIG_DEBUG_USER is not set
|
||
|
CONFIG_DEBUG_ERRORS=y
|
||
|
-CONFIG_DEBUG_LL=y
|
||
|
+# CONFIG_DEBUG_LL is not set
|
||
|
# CONFIG_DEBUG_ICEDCC is not set
|
||
|
# CONFIG_DEBUG_S3C_PORT is not set
|
||
|
CONFIG_DEBUG_S3C_UART=2
|
||
|
diff --git a/drivers/i2c/chips/pcf50633.c b/drivers/i2c/chips/pcf50633.c
|
||
|
index cb4cad8..da58aa3 100644
|
||
|
--- a/drivers/i2c/chips/pcf50633.c
|
||
|
+++ b/drivers/i2c/chips/pcf50633.c
|
||
|
@@ -1466,7 +1466,7 @@ static int pcf50633bl_set_intensity(struct backlight_device *bd)
|
||
|
struct pcf50633_data *pcf = bl_get_data(bd);
|
||
|
int intensity = bd->props.brightness;
|
||
|
int old_intensity = reg_read(pcf, PCF50633_REG_LEDOUT);
|
||
|
- u_int8_t ledena;
|
||
|
+ u_int8_t ledena = 2;
|
||
|
int ret;
|
||
|
|
||
|
if (bd->props.power != FB_BLANK_UNBLANK)
|
||
|
@@ -1474,16 +1474,19 @@ static int pcf50633bl_set_intensity(struct backlight_device *bd)
|
||
|
if (bd->props.fb_blank != FB_BLANK_UNBLANK)
|
||
|
intensity = 0;
|
||
|
|
||
|
- /* The PCF50633 seems to have some kind of oddity (bug?) when
|
||
|
- * the intensity was 0, you need to completely switch it off
|
||
|
- * and re-enable it, before it produces any output voltage again */
|
||
|
+ /* The PCF50633 cannot handle LEDOUT = 0 (datasheet p60)
|
||
|
+ * if seen, you have to re-enable the LED unit
|
||
|
+ */
|
||
|
|
||
|
if (intensity != 0 && old_intensity == 0) {
|
||
|
ledena = reg_read(pcf, PCF50633_REG_LEDENA);
|
||
|
reg_write(pcf, PCF50633_REG_LEDENA, 0x00);
|
||
|
}
|
||
|
|
||
|
- ret = reg_set_bit_mask(pcf, PCF50633_REG_LEDOUT, 0x3f,
|
||
|
+ if (!intensity) /* illegal to set LEDOUT to 0 */
|
||
|
+ ret = reg_set_bit_mask(pcf, PCF50633_REG_LEDOUT, 0x3f, 2);
|
||
|
+ else
|
||
|
+ ret = reg_set_bit_mask(pcf, PCF50633_REG_LEDOUT, 0x3f,
|
||
|
intensity);
|
||
|
|
||
|
if (intensity != 0 && old_intensity == 0)
|
||
|
@@ -1920,6 +1923,8 @@ static int pcf50633_suspend(struct device *dev, pm_message_t state)
|
||
|
}
|
||
|
|
||
|
/* turn off the backlight */
|
||
|
+ __reg_write(pcf, PCF50633_REG_LEDDIM, 0);
|
||
|
+ __reg_write(pcf, PCF50633_REG_LEDOUT, 2);
|
||
|
__reg_write(pcf, PCF50633_REG_LEDENA, 0x00);
|
||
|
|
||
|
pcf->standby_regs.int1m = __reg_read(pcf, PCF50633_REG_INT1M);
|
||
|
@@ -1938,17 +1943,30 @@ static int pcf50633_suspend(struct device *dev, pm_message_t state)
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
+/*
|
||
|
+ * if backlight resume is selected to be deferred by platform, then it
|
||
|
+ * can call this to finally reset backlight status (after LCM is resumed
|
||
|
+ * for example
|
||
|
+ */
|
||
|
+
|
||
|
+void pcf50633_backlight_resume(struct pcf50633_data *pcf)
|
||
|
+{
|
||
|
+ __reg_write(pcf, PCF50633_REG_LEDOUT, pcf->standby_regs.ledout);
|
||
|
+ __reg_write(pcf, PCF50633_REG_LEDENA, pcf->standby_regs.ledena);
|
||
|
+ __reg_write(pcf, PCF50633_REG_LEDDIM, pcf->standby_regs.leddim);
|
||
|
+}
|
||
|
+EXPORT_SYMBOL_GPL(pcf50633_backlight_resume);
|
||
|
+
|
||
|
+
|
||
|
static int pcf50633_resume(struct device *dev)
|
||
|
{
|
||
|
struct i2c_client *client = to_i2c_client(dev);
|
||
|
struct pcf50633_data *pcf = i2c_get_clientdata(client);
|
||
|
int i;
|
||
|
|
||
|
- printk(KERN_INFO"a\n");
|
||
|
/* mutex_lock(&pcf->lock); */ /* resume in atomic context */
|
||
|
|
||
|
__reg_write(pcf, PCF50633_REG_LEDENA, 0x01);
|
||
|
- printk(KERN_INFO"b\n");
|
||
|
|
||
|
/* Resume all saved registers that don't "survive" standby state */
|
||
|
__reg_write(pcf, PCF50633_REG_INT1M, pcf->standby_regs.int1m);
|
||
|
@@ -1956,7 +1974,6 @@ static int pcf50633_resume(struct device *dev)
|
||
|
__reg_write(pcf, PCF50633_REG_INT3M, pcf->standby_regs.int3m);
|
||
|
__reg_write(pcf, PCF50633_REG_INT4M, pcf->standby_regs.int4m);
|
||
|
__reg_write(pcf, PCF50633_REG_INT5M, pcf->standby_regs.int5m);
|
||
|
- printk(KERN_INFO"c\n");
|
||
|
|
||
|
__reg_write(pcf, PCF50633_REG_OOCTIM2, pcf->standby_regs.ooctim2);
|
||
|
__reg_write(pcf, PCF50633_REG_AUTOOUT, pcf->standby_regs.autoout);
|
||
|
@@ -1967,17 +1984,24 @@ static int pcf50633_resume(struct device *dev)
|
||
|
__reg_write(pcf, PCF50633_REG_DOWN2ENA, pcf->standby_regs.down2ena);
|
||
|
__reg_write(pcf, PCF50633_REG_MEMLDOOUT, pcf->standby_regs.memldoout);
|
||
|
__reg_write(pcf, PCF50633_REG_MEMLDOENA, pcf->standby_regs.memldoena);
|
||
|
- __reg_write(pcf, PCF50633_REG_LEDOUT, pcf->standby_regs.ledout);
|
||
|
- __reg_write(pcf, PCF50633_REG_LEDENA, pcf->standby_regs.ledena);
|
||
|
- __reg_write(pcf, PCF50633_REG_LEDDIM, pcf->standby_regs.leddim);
|
||
|
- printk(KERN_INFO"d\n");
|
||
|
+
|
||
|
+ /* platform can choose to defer backlight bringup */
|
||
|
+ if (!pcf->pdata->defer_resume_backlight) {
|
||
|
+ __reg_write(pcf, PCF50633_REG_LEDOUT, pcf->standby_regs.ledout);
|
||
|
+ __reg_write(pcf, PCF50633_REG_LEDENA, pcf->standby_regs.ledena);
|
||
|
+ __reg_write(pcf, PCF50633_REG_LEDDIM, pcf->standby_regs.leddim);
|
||
|
+ } else { /* force backlight down, platform will restore later */
|
||
|
+ __reg_write(pcf, PCF50633_REG_LEDOUT, 2);
|
||
|
+ __reg_write(pcf, PCF50633_REG_LEDENA, 0x20);
|
||
|
+ __reg_write(pcf, PCF50633_REG_LEDDIM, 1);
|
||
|
+ }
|
||
|
+
|
||
|
/* FIXME: one big read? */
|
||
|
for (i = 0; i < 7; i++) {
|
||
|
u_int8_t reg_out = PCF50633_REG_LDO1OUT + 2*i;
|
||
|
__reg_write(pcf, reg_out, pcf->standby_regs.ldo[i].out);
|
||
|
__reg_write(pcf, reg_out+1, pcf->standby_regs.ldo[i].ena);
|
||
|
}
|
||
|
- printk(KERN_INFO"e\n");
|
||
|
|
||
|
/* mutex_unlock(&pcf->lock); */ /* resume in atomic context */
|
||
|
|
||
|
diff --git a/drivers/video/display/jbt6k74.c b/drivers/video/display/jbt6k74.c
|
||
|
index 7e11da7..178e2da 100644
|
||
|
--- a/drivers/video/display/jbt6k74.c
|
||
|
+++ b/drivers/video/display/jbt6k74.c
|
||
|
@@ -647,9 +647,14 @@ static int jbt_suspend(struct spi_device *spi, pm_message_t state)
|
||
|
static void jbt_resume_work(struct work_struct *work)
|
||
|
{
|
||
|
struct jbt_info *jbt = container_of(work, struct jbt_info, work);
|
||
|
+ struct jbt6k74_platform_data *jbt6k74_pdata =
|
||
|
+ jbt->spi_dev->dev.platform_data;
|
||
|
|
||
|
printk(KERN_INFO"jbt_resume_work waiting...\n");
|
||
|
- msleep(2000);
|
||
|
+ /* 100ms is not enough here 2008-05-08 andy@openmoko.com
|
||
|
+ * if CONFIG_PM_DEBUG is enabled 2000ms is required
|
||
|
+ */
|
||
|
+ msleep(400);
|
||
|
printk(KERN_INFO"jbt_resume_work GO...\n");
|
||
|
|
||
|
jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY);
|
||
|
@@ -665,6 +670,11 @@ static void jbt_resume_work(struct work_struct *work)
|
||
|
}
|
||
|
jbt6k74_display_onoff(jbt, 1);
|
||
|
|
||
|
+ /* this gives the platform a chance to bring up backlight now */
|
||
|
+
|
||
|
+ if (jbt6k74_pdata->resuming)
|
||
|
+ (jbt6k74_pdata->resuming)(0);
|
||
|
+
|
||
|
printk(KERN_INFO"jbt_resume_work done...\n");
|
||
|
}
|
||
|
|
||
|
diff --git a/include/linux/jbt6k74.h b/include/linux/jbt6k74.h
|
||
|
index 3fbe178..0ac9124 100644
|
||
|
--- a/include/linux/jbt6k74.h
|
||
|
+++ b/include/linux/jbt6k74.h
|
||
|
@@ -2,7 +2,8 @@
|
||
|
#define __JBT6K74_H__
|
||
|
|
||
|
struct jbt6k74_platform_data {
|
||
|
- void (* reset)(int devindex, int level);
|
||
|
+ void (*reset)(int devindex, int level);
|
||
|
+ void (*resuming)(int devindex); /* called when LCM is resumed */
|
||
|
};
|
||
|
|
||
|
#endif
|
||
|
diff --git a/include/linux/pcf50633.h b/include/linux/pcf50633.h
|
||
|
index b6a67ee..f427985 100644
|
||
|
--- a/include/linux/pcf50633.h
|
||
|
+++ b/include/linux/pcf50633.h
|
||
|
@@ -61,6 +61,9 @@ pcf50633_usb_curlim_set(struct pcf50633_data *pcf, int ma);
|
||
|
extern void
|
||
|
pcf50633_charge_enable(struct pcf50633_data *pcf, int on);
|
||
|
|
||
|
+extern void
|
||
|
+pcf50633_backlight_resume(struct pcf50633_data *pcf);
|
||
|
+
|
||
|
#define PCF50633_FEAT_EXTON 0x00000001 /* not yet supported */
|
||
|
#define PCF50633_FEAT_MBC 0x00000002
|
||
|
#define PCF50633_FEAT_BBC 0x00000004 /* not yet supported */
|
||
|
@@ -89,6 +92,9 @@ struct pcf50633_platform_data {
|
||
|
u_int8_t mbcc3; /* charger voltage / current */
|
||
|
} charger;
|
||
|
pmu_cb *cb;
|
||
|
+
|
||
|
+ /* post-resume backlight bringup */
|
||
|
+ int defer_resume_backlight;
|
||
|
};
|
||
|
|
||
|
#endif /* _PCF50633_H */
|
||
|
--
|
||
|
1.5.6.3
|
||
|
|