disable IMQ on 2.6.28 as well -- people should use IFB..
[openwrt.git] / target / linux / s3c24xx / patches / 0138-fix-suspend-backlight-timing-pm-debug.patch.patch
1 From 36b19597a232bb198b3bab4003c0f0807c821274 Mon Sep 17 00:00:00 2001
2 From: Andy Green <andy@openmoko.com>
3 Date: Fri, 25 Jul 2008 23:06:08 +0100
4 Subject: [PATCH] fix-suspend-backlight-timing-pm-debug.patch
5
6 This patch improves the smoothness of suspend and resume action.
7
8 Taking out CONFIG_PM_DEBUG allows much more rapid resume (the low level
9 serial traffic appears to be synchronous)
10
11 Added a platform callback in jbt driver and support in pcf50633 so we
12 can defer bringing up the backlight until the LCM is able to process
13 video again (which must happen after the glamo is up and producing
14 video beacuse the LCM is hooked to glamo SPI)
15
16 GTA01 should not be affected by all this as the callback will default
17 to null and it is on pcf50606
18
19 Signed-off-by: Andy Green <andy@openmoko.com>
20 ---
21  arch/arm/mach-s3c2440/mach-gta02.c |    8 ++++++
22  defconfig-2.6.24                   |    4 +-
23  drivers/i2c/chips/pcf50633.c       |   50 ++++++++++++++++++++++++++---------
24  drivers/video/display/jbt6k74.c    |   12 ++++++++-
25  include/linux/jbt6k74.h            |    3 +-
26  include/linux/pcf50633.h           |    6 ++++
27  6 files changed, 66 insertions(+), 17 deletions(-)
28
29 diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
30 index 1954121..e1984a9 100644
31 --- a/arch/arm/mach-s3c2440/mach-gta02.c
32 +++ b/arch/arm/mach-s3c2440/mach-gta02.c
33 @@ -532,6 +532,7 @@ static struct pcf50633_platform_data gta02_pcf_pdata = {
34                         },
35                 },
36         },
37 +       .defer_resume_backlight = 1,
38  };
39  
40  #if 0 /* currently unused */
41 @@ -828,9 +829,16 @@ void gta02_jbt6k74_reset(int devidx, int level)
42         glamo_lcm_reset(level);
43  }
44  
45 +/* finally bring up deferred backlight resume now LCM is resumed itself */
46 +
47 +void gta02_jbt6k74_resuming(int devidx)
48 +{
49 +       pcf50633_backlight_resume(pcf50633_global);
50 +}
51  
52  const struct jbt6k74_platform_data jbt6k74_pdata = {
53         .reset          = gta02_jbt6k74_reset,
54 +       .resuming       = gta02_jbt6k74_resuming,
55  };
56  
57  static struct spi_board_info gta02_spi_board_info[] = {
58 diff --git a/defconfig-2.6.24 b/defconfig-2.6.24
59 index 4df10bf..34fa961 100644
60 --- a/defconfig-2.6.24
61 +++ b/defconfig-2.6.24
62 @@ -161,7 +161,7 @@ CONFIG_CPU_LLSERIAL_S3C2440=y
63  #
64  # Power management
65  #
66 -CONFIG_S3C2410_PM_DEBUG=y
67 +# CONFIG_S3C2410_PM_DEBUG is not set
68  # CONFIG_S3C2410_PM_CHECK is not set
69  CONFIG_S3C_LOWLEVEL_UART_PORT=2
70  
71 @@ -1754,7 +1754,7 @@ CONFIG_FORCED_INLINING=y
72  # CONFIG_SAMPLES is not set
73  # CONFIG_DEBUG_USER is not set
74  CONFIG_DEBUG_ERRORS=y
75 -CONFIG_DEBUG_LL=y
76 +# CONFIG_DEBUG_LL is not set
77  # CONFIG_DEBUG_ICEDCC is not set
78  # CONFIG_DEBUG_S3C_PORT is not set
79  CONFIG_DEBUG_S3C_UART=2
80 diff --git a/drivers/i2c/chips/pcf50633.c b/drivers/i2c/chips/pcf50633.c
81 index cb4cad8..da58aa3 100644
82 --- a/drivers/i2c/chips/pcf50633.c
83 +++ b/drivers/i2c/chips/pcf50633.c
84 @@ -1466,7 +1466,7 @@ static int pcf50633bl_set_intensity(struct backlight_device *bd)
85         struct pcf50633_data *pcf = bl_get_data(bd);
86         int intensity = bd->props.brightness;
87         int old_intensity = reg_read(pcf, PCF50633_REG_LEDOUT);
88 -       u_int8_t ledena;
89 +       u_int8_t ledena = 2;
90         int ret;
91  
92         if (bd->props.power != FB_BLANK_UNBLANK)
93 @@ -1474,16 +1474,19 @@ static int pcf50633bl_set_intensity(struct backlight_device *bd)
94         if (bd->props.fb_blank != FB_BLANK_UNBLANK)
95                 intensity = 0;
96  
97 -       /* The PCF50633 seems to have some kind of oddity (bug?) when
98 -        * the intensity was 0, you need to completely switch it off
99 -        * and re-enable it, before it produces any output voltage again */
100 +       /* The PCF50633 cannot handle LEDOUT = 0 (datasheet p60)
101 +        * if seen, you have to re-enable the LED unit
102 +        */
103  
104         if (intensity != 0 && old_intensity == 0) {
105                 ledena = reg_read(pcf, PCF50633_REG_LEDENA);
106                 reg_write(pcf, PCF50633_REG_LEDENA, 0x00);
107         }
108  
109 -       ret = reg_set_bit_mask(pcf, PCF50633_REG_LEDOUT, 0x3f,
110 +       if (!intensity) /* illegal to set LEDOUT to 0 */
111 +               ret = reg_set_bit_mask(pcf, PCF50633_REG_LEDOUT, 0x3f, 2);
112 +       else
113 +               ret = reg_set_bit_mask(pcf, PCF50633_REG_LEDOUT, 0x3f,
114                                intensity);
115  
116         if (intensity != 0 && old_intensity == 0)
117 @@ -1920,6 +1923,8 @@ static int pcf50633_suspend(struct device *dev, pm_message_t state)
118         }
119  
120         /* turn off the backlight */
121 +       __reg_write(pcf, PCF50633_REG_LEDDIM, 0);
122 +       __reg_write(pcf, PCF50633_REG_LEDOUT, 2);
123         __reg_write(pcf, PCF50633_REG_LEDENA, 0x00);
124  
125         pcf->standby_regs.int1m = __reg_read(pcf, PCF50633_REG_INT1M);
126 @@ -1938,17 +1943,30 @@ static int pcf50633_suspend(struct device *dev, pm_message_t state)
127         return 0;
128  }
129  
130 +/*
131 + * if backlight resume is selected to be deferred by platform, then it
132 + * can call this to finally reset backlight status (after LCM is resumed
133 + * for example
134 + */
135 +
136 +void pcf50633_backlight_resume(struct pcf50633_data *pcf)
137 +{
138 +       __reg_write(pcf, PCF50633_REG_LEDOUT, pcf->standby_regs.ledout);
139 +       __reg_write(pcf, PCF50633_REG_LEDENA, pcf->standby_regs.ledena);
140 +       __reg_write(pcf, PCF50633_REG_LEDDIM, pcf->standby_regs.leddim);
141 +}
142 +EXPORT_SYMBOL_GPL(pcf50633_backlight_resume);
143 +
144 +
145  static int pcf50633_resume(struct device *dev)
146  {
147         struct i2c_client *client = to_i2c_client(dev);
148         struct pcf50633_data *pcf = i2c_get_clientdata(client);
149         int i;
150  
151 -       printk(KERN_INFO"a\n");
152         /* mutex_lock(&pcf->lock); */  /* resume in atomic context */
153  
154         __reg_write(pcf, PCF50633_REG_LEDENA, 0x01);
155 -       printk(KERN_INFO"b\n");
156  
157         /* Resume all saved registers that don't "survive" standby state */
158         __reg_write(pcf, PCF50633_REG_INT1M, pcf->standby_regs.int1m);
159 @@ -1956,7 +1974,6 @@ static int pcf50633_resume(struct device *dev)
160         __reg_write(pcf, PCF50633_REG_INT3M, pcf->standby_regs.int3m);
161         __reg_write(pcf, PCF50633_REG_INT4M, pcf->standby_regs.int4m);
162         __reg_write(pcf, PCF50633_REG_INT5M, pcf->standby_regs.int5m);
163 -       printk(KERN_INFO"c\n");
164  
165         __reg_write(pcf, PCF50633_REG_OOCTIM2, pcf->standby_regs.ooctim2);
166         __reg_write(pcf, PCF50633_REG_AUTOOUT, pcf->standby_regs.autoout);
167 @@ -1967,17 +1984,24 @@ static int pcf50633_resume(struct device *dev)
168         __reg_write(pcf, PCF50633_REG_DOWN2ENA, pcf->standby_regs.down2ena);
169         __reg_write(pcf, PCF50633_REG_MEMLDOOUT, pcf->standby_regs.memldoout);
170         __reg_write(pcf, PCF50633_REG_MEMLDOENA, pcf->standby_regs.memldoena);
171 -       __reg_write(pcf, PCF50633_REG_LEDOUT, pcf->standby_regs.ledout);
172 -       __reg_write(pcf, PCF50633_REG_LEDENA, pcf->standby_regs.ledena);
173 -       __reg_write(pcf, PCF50633_REG_LEDDIM, pcf->standby_regs.leddim);
174 -       printk(KERN_INFO"d\n");
175 +
176 +       /* platform can choose to defer backlight bringup */
177 +       if (!pcf->pdata->defer_resume_backlight) {
178 +               __reg_write(pcf, PCF50633_REG_LEDOUT, pcf->standby_regs.ledout);
179 +               __reg_write(pcf, PCF50633_REG_LEDENA, pcf->standby_regs.ledena);
180 +               __reg_write(pcf, PCF50633_REG_LEDDIM, pcf->standby_regs.leddim);
181 +       } else { /* force backlight down, platform will restore later */
182 +               __reg_write(pcf, PCF50633_REG_LEDOUT, 2);
183 +               __reg_write(pcf, PCF50633_REG_LEDENA, 0x20);
184 +               __reg_write(pcf, PCF50633_REG_LEDDIM, 1);
185 +       }
186 +
187         /* FIXME: one big read? */
188         for (i = 0; i < 7; i++) {
189                 u_int8_t reg_out = PCF50633_REG_LDO1OUT + 2*i;
190                 __reg_write(pcf, reg_out, pcf->standby_regs.ldo[i].out);
191                 __reg_write(pcf, reg_out+1, pcf->standby_regs.ldo[i].ena);
192         }
193 -       printk(KERN_INFO"e\n");
194  
195         /* mutex_unlock(&pcf->lock); */ /* resume in atomic context */
196  
197 diff --git a/drivers/video/display/jbt6k74.c b/drivers/video/display/jbt6k74.c
198 index 7e11da7..178e2da 100644
199 --- a/drivers/video/display/jbt6k74.c
200 +++ b/drivers/video/display/jbt6k74.c
201 @@ -647,9 +647,14 @@ static int jbt_suspend(struct spi_device *spi, pm_message_t state)
202  static void jbt_resume_work(struct work_struct *work)
203  {
204         struct jbt_info *jbt = container_of(work, struct jbt_info, work);
205 +       struct jbt6k74_platform_data *jbt6k74_pdata =
206 +                                               jbt->spi_dev->dev.platform_data;
207  
208         printk(KERN_INFO"jbt_resume_work waiting...\n");
209 -       msleep(2000);
210 +       /* 100ms is not enough here 2008-05-08 andy@openmoko.com
211 +        * if CONFIG_PM_DEBUG is enabled 2000ms is required
212 +        */
213 +       msleep(400);
214         printk(KERN_INFO"jbt_resume_work GO...\n");
215  
216         jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY);
217 @@ -665,6 +670,11 @@ static void jbt_resume_work(struct work_struct *work)
218         }
219         jbt6k74_display_onoff(jbt, 1);
220  
221 +       /* this gives the platform a chance to bring up backlight now */
222 +
223 +       if (jbt6k74_pdata->resuming)
224 +               (jbt6k74_pdata->resuming)(0);
225 +
226         printk(KERN_INFO"jbt_resume_work done...\n");
227  }
228  
229 diff --git a/include/linux/jbt6k74.h b/include/linux/jbt6k74.h
230 index 3fbe178..0ac9124 100644
231 --- a/include/linux/jbt6k74.h
232 +++ b/include/linux/jbt6k74.h
233 @@ -2,7 +2,8 @@
234  #define __JBT6K74_H__
235  
236  struct jbt6k74_platform_data {
237 -       void (* reset)(int devindex, int level);
238 +       void (*reset)(int devindex, int level);
239 +       void (*resuming)(int devindex); /* called when LCM is resumed */
240  };
241  
242  #endif
243 diff --git a/include/linux/pcf50633.h b/include/linux/pcf50633.h
244 index b6a67ee..f427985 100644
245 --- a/include/linux/pcf50633.h
246 +++ b/include/linux/pcf50633.h
247 @@ -61,6 +61,9 @@ pcf50633_usb_curlim_set(struct pcf50633_data *pcf, int ma);
248  extern void
249  pcf50633_charge_enable(struct pcf50633_data *pcf, int on);
250  
251 +extern void
252 +pcf50633_backlight_resume(struct pcf50633_data *pcf);
253 +
254  #define PCF50633_FEAT_EXTON    0x00000001      /* not yet supported */
255  #define PCF50633_FEAT_MBC      0x00000002
256  #define PCF50633_FEAT_BBC      0x00000004      /* not yet supported */
257 @@ -89,6 +92,9 @@ struct pcf50633_platform_data {
258                 u_int8_t mbcc3; /* charger voltage / current */
259         } charger;
260         pmu_cb *cb;
261 +
262 +       /* post-resume backlight bringup */
263 +       int defer_resume_backlight;
264  };
265  
266  #endif /* _PCF50633_H */
267 -- 
268 1.5.6.3
269