1 From f2cf4e5f204e981a02a0edaccab4ca39f868ac0f Mon Sep 17 00:00:00 2001
2 From: Andy Green <andy@openmoko.com>
3 Date: Sun, 13 Apr 2008 07:25:56 +0100
4 Subject: [PATCH] fix-glamofb-cmd-mode-locking.patch
6 Glamo "cmd mode" is modal, but nothing took care about locking.
7 Also cmd mode was entered recursively in rotate_lcd().
9 Signed-off-by: Andy Green <andy@openmoko.com>
11 drivers/mfd/glamo/glamo-core.c | 2 +-
12 drivers/mfd/glamo/glamo-fb.c | 106 +++++++++++++++++++++++++--------------
13 include/linux/glamofb.h | 2 +-
14 3 files changed, 70 insertions(+), 40 deletions(-)
16 diff --git a/drivers/mfd/glamo/glamo-core.c b/drivers/mfd/glamo/glamo-core.c
17 index accd933..19ca363 100644
18 --- a/drivers/mfd/glamo/glamo-core.c
19 +++ b/drivers/mfd/glamo/glamo-core.c
20 @@ -588,7 +588,7 @@ int glamo_engine_reclock(struct glamo_core *glamo,
23 reg_set_bit_mask(glamo, reg, mask, val);
24 - msleep(5); /* wait some time to stabilize */
25 + mdelay(5); /* wait some time to stabilize */
29 diff --git a/drivers/mfd/glamo/glamo-fb.c b/drivers/mfd/glamo/glamo-fb.c
30 index 87c7420..8633e44 100644
31 --- a/drivers/mfd/glamo/glamo-fb.c
32 +++ b/drivers/mfd/glamo/glamo-fb.c
34 #include <linux/wait.h>
35 #include <linux/platform_device.h>
36 #include <linux/clk.h>
37 +#include <linux/spinlock.h>
40 #include <asm/uaccess.h>
42 #include "glamo-regs.h"
43 #include "glamo-core.h"
47 #define GLAMO_LOG(...)
49 #define GLAMO_LOG(...) \
50 @@ -72,6 +73,7 @@ struct glamofb_handle {
51 struct glamofb_platform_data *mach_info;
52 char __iomem *cursor_addr;
53 u_int32_t pseudo_pal[16];
54 + spinlock_t lock_cmd;
57 /* 'sibling' spi device for lcm init */
58 @@ -237,6 +239,7 @@ static void rotate_lcd(struct glamofb_handle *glamo,
62 + unsigned long flags;
66 @@ -255,7 +258,15 @@ static void rotate_lcd(struct glamofb_handle *glamo,
67 glamo_rot = GLAMO_LCD_ROT_MODE_0;
70 - glamofb_cmd_mode(glamo, 1);
73 + * ha ha we are only called when we are in cmd mode already
74 + * printk(KERN_ERR"rotate_lcd spin_lock_irqsave\n");
75 + * spin_lock_irqsave(&glamo->lock_cmd, flags);
77 + * if (glamofb_cmd_mode(glamo, 1))
80 reg_set_bit_mask(glamo,
82 GLAMO_LCD_ROT_MODE_MASK,
83 @@ -265,17 +276,19 @@ static void rotate_lcd(struct glamofb_handle *glamo,
84 GLAMO_LCD_MODE1_ROTATE_EN,
85 (glamo_rot != GLAMO_LCD_ROT_MODE_0)?
86 GLAMO_LCD_MODE1_ROTATE_EN : 0);
87 - glamofb_cmd_mode(glamo, 0);
88 +/* glamofb_cmd_mode(glamo, 0);
91 + printk(KERN_ERR"rotate_lcd spin_unlock_irqrestore\n");
92 + spin_unlock_irqrestore(&glamo->lock_cmd, flags);
96 static enum orientation get_orientation(struct fb_var_screeninfo *var)
99 - if (var->xres <= var->yres) {
100 - GLAMO_LOG("portrait\n")
101 + if (var->xres <= var->yres)
102 return ORIENTATION_PORTRAIT;
104 - GLAMO_LOG("landscape\n")
106 return ORIENTATION_LANDSCAPE;
109 @@ -299,12 +312,18 @@ static void glamofb_update_lcd_controller(struct glamofb_handle *glamo,
110 struct fb_var_screeninfo *var)
112 int sync, bp, disp, fp, total, xres, yres, pitch, orientation_changing;
113 + unsigned long flags;
115 - GLAMO_LOG("enter: glamo:%#x, var:%#x\n", (unsigned)glamo, (unsigned)var);
116 +/* GLAMO_LOG("enter: glamo:%#x, var:%#x\n", (unsigned)glamo, (unsigned)var);
121 - glamofb_cmd_mode(glamo, 1);
122 + printk(KERN_ERR"glamofb_update_lcd_controller spin_lock_irqsave\n");
123 + spin_lock_irqsave(&glamo->lock_cmd, flags);
125 + if (glamofb_cmd_mode(glamo, 1))
129 glamo_engine_reclock(glamo->mach_info->glamo,
130 @@ -313,14 +332,14 @@ static void glamofb_update_lcd_controller(struct glamofb_handle *glamo,
134 - GLAMO_LOG("xres:%d, yres:%d, rotate:%d\n", xres, yres, var->rotate);
136 +/* GLAMO_LOG("xres:%d, yres:%d, rotate:%d\n", xres, yres, var->rotate);
139 * figure out if orientation is going to change
141 orientation_changing = will_orientation_change(var);
142 - GLAMO_LOG("orientation_changing:%d\n", orientation_changing);
144 +/* GLAMO_LOG("orientation_changing:%d\n", orientation_changing);
147 * adjust the pitch according to new orientation to come
149 @@ -329,8 +348,8 @@ static void glamofb_update_lcd_controller(struct glamofb_handle *glamo,
151 pitch = var->xres * var->bits_per_pixel / 8;
153 - GLAMO_LOG("pitch:%d\n", pitch);
155 +/* GLAMO_LOG("pitch:%d\n", pitch);
158 * set the awaiten LCD geometry
160 @@ -347,7 +366,7 @@ static void glamofb_update_lcd_controller(struct glamofb_handle *glamo,
161 GLAMO_LCD_PITCH_MASK,
164 - GLAMO_LOG("mark:\n");
165 +/* GLAMO_LOG("mark:\n");*/
167 * honour the rotation request
169 @@ -365,7 +384,8 @@ static void glamofb_update_lcd_controller(struct glamofb_handle *glamo,
170 var->yres_virtual = var->yres = yres;
173 - GLAMO_LOG("reported res:(%d,%d)\n", var->xres, var->yres);
174 +/* GLAMO_LOG("reported res:(%d,%d)\n", var->xres, var->yres);
177 * update scannout timings
179 @@ -386,8 +406,8 @@ static void glamofb_update_lcd_controller(struct glamofb_handle *glamo,
180 reg_set_bit_mask(glamo, GLAMO_REG_LCD_HORIZ_DISP_END,
181 GLAMO_LCD_HV_RETR_DISP_END_MASK, fp);
183 - GLAMO_LOG("mark:\n");
185 +/* GLAMO_LOG("mark:\n");
188 bp = sync + var->vsync_len;
189 disp = bp + var->upper_margin;
190 @@ -405,10 +425,13 @@ static void glamofb_update_lcd_controller(struct glamofb_handle *glamo,
191 reg_set_bit_mask(glamo, GLAMO_REG_LCD_VERT_DISP_END,
192 GLAMO_LCD_HV_RETR_DISP_END_MASK, fp);
194 - GLAMO_LOG("mark:\n");
195 +/* GLAMO_LOG("mark:\n"); */
196 glamofb_cmd_mode(glamo, 0);
198 - GLAMO_LOG("leave:\n");
199 +/* GLAMO_LOG("leave:\n"); */
201 + printk(KERN_ERR"glamofb_update_lcd_controller spin_unlock_irqrestore\n");
202 + spin_unlock_irqrestore(&glamo->lock_cmd, flags);
205 static int glamofb_set_par(struct fb_info *info)
206 @@ -552,23 +575,25 @@ static inline int glamofb_cmdq_empty(struct glamofb_handle *gfb)
207 return reg_read(gfb, GLAMO_REG_LCD_STATUS1) & (1 << 15);
210 -void glamofb_cmd_mode(struct glamofb_handle *gfb, int on)
211 +/* call holding gfb->lock_cmd when locking, until you unlock */
213 +int glamofb_cmd_mode(struct glamofb_handle *gfb, int on)
215 - int timeout = 20000;
216 + int timeout = 200000;
218 - dev_dbg(gfb->dev, "glamofb_cmd_mode(gfb=%p, on=%d)\n", gfb, on);
219 +/* dev_dbg(gfb->dev, "glamofb_cmd_mode(gfb=%p, on=%d)\n", gfb, on); */
221 - dev_dbg(gfb->dev, "%s: waiting for cmdq empty: ",
223 +/* dev_dbg(gfb->dev, "%s: waiting for cmdq empty: ",
225 while ((!glamofb_cmdq_empty(gfb)) && (timeout--))
228 printk(KERN_ERR"*************"
229 "glamofb cmd_queue never got empty"
234 - dev_dbg(gfb->dev, "empty!\n");
235 +/* dev_dbg(gfb->dev, "empty!\n"); */
237 /* display the entire frame then switch to command */
238 reg_write(gfb, GLAMO_REG_LCD_COMMAND1,
239 @@ -576,8 +601,8 @@ void glamofb_cmd_mode(struct glamofb_handle *gfb, int on)
240 GLAMO_LCD_CMD_DATA_FIRE_VSYNC);
242 /* wait until LCD is idle */
243 - dev_dbg(gfb->dev, "waiting for LCD idle: ");
245 +/* dev_dbg(gfb->dev, "waiting for LCD idle: "); */
247 while ((!reg_read(gfb, GLAMO_REG_LCD_STATUS2) & (1 << 12)) &&
250 @@ -585,11 +610,11 @@ void glamofb_cmd_mode(struct glamofb_handle *gfb, int on)
251 printk(KERN_ERR"*************"
252 "glamofb lcd never idle"
257 - dev_dbg(gfb->dev, "idle!\n");
258 +/* dev_dbg(gfb->dev, "idle!\n"); */
263 /* RGB interface needs vsync/hsync */
264 if (reg_read(gfb, GLAMO_REG_LCD_MODE3) & GLAMO_LCD_MODE3_RGB)
265 @@ -601,15 +626,17 @@ void glamofb_cmd_mode(struct glamofb_handle *gfb, int on)
266 GLAMO_LCD_CMD_TYPE_DISP |
267 GLAMO_LCD_CMD_DATA_DISP_FIRE);
272 EXPORT_SYMBOL_GPL(glamofb_cmd_mode);
274 int glamofb_cmd_write(struct glamofb_handle *gfb, u_int16_t val)
276 - int timeout = 20000;
277 + int timeout = 200000;
279 - dev_dbg(gfb->dev, "%s: waiting for cmdq empty\n",
281 +/* dev_dbg(gfb->dev, "%s: waiting for cmdq empty\n",
283 while ((!glamofb_cmdq_empty(gfb)) && (timeout--))
286 @@ -618,7 +645,7 @@ int glamofb_cmd_write(struct glamofb_handle *gfb, u_int16_t val)
290 - dev_dbg(gfb->dev, "idle, writing 0x%04x\n", val);
291 +/* dev_dbg(gfb->dev, "idle, writing 0x%04x\n", val); */
293 reg_write(gfb, GLAMO_REG_LCD_COMMAND1, val);
295 @@ -758,6 +785,9 @@ static int __init glamofb_probe(struct platform_device *pdev)
297 glamo_engine_enable(mach_info->glamo, GLAMO_ENGINE_LCD);
298 glamo_engine_reset(mach_info->glamo, GLAMO_ENGINE_LCD);
300 + printk(KERN_ERR"spin_lock_init\n");
301 + spin_lock_init(&glamofb->lock_cmd);
302 glamofb_init_regs(glamofb);
304 rc = register_framebuffer(fbinfo);
305 diff --git a/include/linux/glamofb.h b/include/linux/glamofb.h
306 index 75eefef..51bf593 100644
307 --- a/include/linux/glamofb.h
308 +++ b/include/linux/glamofb.h
309 @@ -33,7 +33,7 @@ struct glamofb_platform_data {
310 int (*glamo_irq_is_wired)(void);
313 -void glamofb_cmd_mode(struct glamofb_handle *gfb, int on);
314 +int glamofb_cmd_mode(struct glamofb_handle *gfb, int on);
315 int glamofb_cmd_write(struct glamofb_handle *gfb, u_int16_t val);
316 void glamo_lcm_reset(int level);