1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
|
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
|