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
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
|
From 863d980d4392041b36edd53b248ae7709609325d Mon Sep 17 00:00:00 2001
From: Andy Green <andy@openmoko.com>
Date: Fri, 25 Jul 2008 23:06:04 +0100
Subject: [PATCH] fix-glamofb-cmd-mode-locking.patch
Glamo "cmd mode" is modal, but nothing took care about locking.
Also cmd mode was entered recursively in rotate_lcd().
Signed-off-by: Andy Green <andy@openmoko.com>
---
drivers/mfd/glamo/glamo-core.c | 2 +-
drivers/mfd/glamo/glamo-fb.c | 106 +++++++++++++++++++++++++--------------
include/linux/glamofb.h | 2 +-
3 files changed, 70 insertions(+), 40 deletions(-)
diff --git a/drivers/mfd/glamo/glamo-core.c b/drivers/mfd/glamo/glamo-core.c
index accd933..19ca363 100644
--- a/drivers/mfd/glamo/glamo-core.c
+++ b/drivers/mfd/glamo/glamo-core.c
@@ -588,7 +588,7 @@ int glamo_engine_reclock(struct glamo_core *glamo,
if (val) {
val--;
reg_set_bit_mask(glamo, reg, mask, val);
- msleep(5); /* wait some time to stabilize */
+ mdelay(5); /* wait some time to stabilize */
return 0;
} else {
diff --git a/drivers/mfd/glamo/glamo-fb.c b/drivers/mfd/glamo/glamo-fb.c
index 87c7420..8633e44 100644
--- a/drivers/mfd/glamo/glamo-fb.c
+++ b/drivers/mfd/glamo/glamo-fb.c
@@ -36,6 +36,7 @@
#include <linux/wait.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <linux/spinlock.h>
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -50,7 +51,7 @@
#include "glamo-regs.h"
#include "glamo-core.h"
-#ifdef DEBUG
+#ifndef DEBUG
#define GLAMO_LOG(...)
#else
#define GLAMO_LOG(...) \
@@ -72,6 +73,7 @@ struct glamofb_handle {
struct glamofb_platform_data *mach_info;
char __iomem *cursor_addr;
u_int32_t pseudo_pal[16];
+ spinlock_t lock_cmd;
};
/* 'sibling' spi device for lcm init */
@@ -237,6 +239,7 @@ static void rotate_lcd(struct glamofb_handle *glamo,
__u32 rotation)
{
int glamo_rot;
+ unsigned long flags;
switch (rotation) {
case FB_ROTATE_UR:
@@ -255,7 +258,15 @@ static void rotate_lcd(struct glamofb_handle *glamo,
glamo_rot = GLAMO_LCD_ROT_MODE_0;
break;
}
- glamofb_cmd_mode(glamo, 1);
+
+ /*
+ * ha ha we are only called when we are in cmd mode already
+ * printk(KERN_ERR"rotate_lcd spin_lock_irqsave\n");
+ * spin_lock_irqsave(&glamo->lock_cmd, flags);
+ *
+ * if (glamofb_cmd_mode(glamo, 1))
+ * goto out_unlock;
+ */
reg_set_bit_mask(glamo,
GLAMO_REG_LCD_WIDTH,
GLAMO_LCD_ROT_MODE_MASK,
@@ -265,17 +276,19 @@ static void rotate_lcd(struct glamofb_handle *glamo,
GLAMO_LCD_MODE1_ROTATE_EN,
(glamo_rot != GLAMO_LCD_ROT_MODE_0)?
GLAMO_LCD_MODE1_ROTATE_EN : 0);
- glamofb_cmd_mode(glamo, 0);
+/* glamofb_cmd_mode(glamo, 0);
+
+out_unlock:
+ printk(KERN_ERR"rotate_lcd spin_unlock_irqrestore\n");
+ spin_unlock_irqrestore(&glamo->lock_cmd, flags);
+*/
}
static enum orientation get_orientation(struct fb_var_screeninfo *var)
{
- GLAMO_LOG("mark\n")
- if (var->xres <= var->yres) {
- GLAMO_LOG("portrait\n")
+ if (var->xres <= var->yres)
return ORIENTATION_PORTRAIT;
- }
- GLAMO_LOG("landscape\n")
+
return ORIENTATION_LANDSCAPE;
}
@@ -299,12 +312,18 @@ static void glamofb_update_lcd_controller(struct glamofb_handle *glamo,
struct fb_var_screeninfo *var)
{
int sync, bp, disp, fp, total, xres, yres, pitch, orientation_changing;
+ unsigned long flags;
- GLAMO_LOG("enter: glamo:%#x, var:%#x\n", (unsigned)glamo, (unsigned)var);
+/* GLAMO_LOG("enter: glamo:%#x, var:%#x\n", (unsigned)glamo, (unsigned)var);
+*/
if (!glamo || !var)
return;
- glamofb_cmd_mode(glamo, 1);
+ printk(KERN_ERR"glamofb_update_lcd_controller spin_lock_irqsave\n");
+ spin_lock_irqsave(&glamo->lock_cmd, flags);
+
+ if (glamofb_cmd_mode(glamo, 1))
+ goto out_unlock;
if (var->pixclock)
glamo_engine_reclock(glamo->mach_info->glamo,
@@ -313,14 +332,14 @@ static void glamofb_update_lcd_controller(struct glamofb_handle *glamo,
xres = var->xres;
yres = var->yres;
- GLAMO_LOG("xres:%d, yres:%d, rotate:%d\n", xres, yres, var->rotate);
-
+/* GLAMO_LOG("xres:%d, yres:%d, rotate:%d\n", xres, yres, var->rotate);
+*/
/*
* figure out if orientation is going to change
*/
orientation_changing = will_orientation_change(var);
- GLAMO_LOG("orientation_changing:%d\n", orientation_changing);
-
+/* GLAMO_LOG("orientation_changing:%d\n", orientation_changing);
+*/
/*
* adjust the pitch according to new orientation to come
*/
@@ -329,8 +348,8 @@ static void glamofb_update_lcd_controller(struct glamofb_handle *glamo,
} else {
pitch = var->xres * var->bits_per_pixel / 8;
}
- GLAMO_LOG("pitch:%d\n", pitch);
-
+/* GLAMO_LOG("pitch:%d\n", pitch);
+*/
/*
* set the awaiten LCD geometry
*/
@@ -347,7 +366,7 @@ static void glamofb_update_lcd_controller(struct glamofb_handle *glamo,
GLAMO_LCD_PITCH_MASK,
pitch);
- GLAMO_LOG("mark:\n");
+/* GLAMO_LOG("mark:\n");*/
/*
* honour the rotation request
*/
@@ -365,7 +384,8 @@ static void glamofb_update_lcd_controller(struct glamofb_handle *glamo,
var->yres_virtual = var->yres = yres;
}
- GLAMO_LOG("reported res:(%d,%d)\n", var->xres, var->yres);
+/* GLAMO_LOG("reported res:(%d,%d)\n", var->xres, var->yres);
+*/
/*
* update scannout timings
*/
@@ -386,8 +406,8 @@ static void glamofb_update_lcd_controller(struct glamofb_handle *glamo,
reg_set_bit_mask(glamo, GLAMO_REG_LCD_HORIZ_DISP_END,
GLAMO_LCD_HV_RETR_DISP_END_MASK, fp);
- GLAMO_LOG("mark:\n");
-
+/* GLAMO_LOG("mark:\n");
+*/
sync = 0;
bp = sync + var->vsync_len;
disp = bp + var->upper_margin;
@@ -405,10 +425,13 @@ static void glamofb_update_lcd_controller(struct glamofb_handle *glamo,
reg_set_bit_mask(glamo, GLAMO_REG_LCD_VERT_DISP_END,
GLAMO_LCD_HV_RETR_DISP_END_MASK, fp);
- GLAMO_LOG("mark:\n");
+/* GLAMO_LOG("mark:\n"); */
glamofb_cmd_mode(glamo, 0);
- GLAMO_LOG("leave:\n");
+/* GLAMO_LOG("leave:\n"); */
+out_unlock:
+ printk(KERN_ERR"glamofb_update_lcd_controller spin_unlock_irqrestore\n");
+ spin_unlock_irqrestore(&glamo->lock_cmd, flags);
}
static int glamofb_set_par(struct fb_info *info)
@@ -552,23 +575,25 @@ static inline int glamofb_cmdq_empty(struct glamofb_handle *gfb)
return reg_read(gfb, GLAMO_REG_LCD_STATUS1) & (1 << 15);
}
-void glamofb_cmd_mode(struct glamofb_handle *gfb, int on)
+/* call holding gfb->lock_cmd when locking, until you unlock */
+
+int glamofb_cmd_mode(struct glamofb_handle *gfb, int on)
{
- int timeout = 20000;
+ int timeout = 200000;
- dev_dbg(gfb->dev, "glamofb_cmd_mode(gfb=%p, on=%d)\n", gfb, on);
+/* dev_dbg(gfb->dev, "glamofb_cmd_mode(gfb=%p, on=%d)\n", gfb, on); */
if (on) {
- dev_dbg(gfb->dev, "%s: waiting for cmdq empty: ",
- __FUNCTION__);
+/* dev_dbg(gfb->dev, "%s: waiting for cmdq empty: ",
+ __FUNCTION__); */
while ((!glamofb_cmdq_empty(gfb)) && (timeout--))
yield();
if (timeout < 0) {
printk(KERN_ERR"*************"
"glamofb cmd_queue never got empty"
"*************\n");
- return;
+ return -EIO;
}
- dev_dbg(gfb->dev, "empty!\n");
+/* dev_dbg(gfb->dev, "empty!\n"); */
/* display the entire frame then switch to command */
reg_write(gfb, GLAMO_REG_LCD_COMMAND1,
@@ -576,8 +601,8 @@ void glamofb_cmd_mode(struct glamofb_handle *gfb, int on)
GLAMO_LCD_CMD_DATA_FIRE_VSYNC);
/* wait until LCD is idle */
- dev_dbg(gfb->dev, "waiting for LCD idle: ");
- timeout = 2000;
+/* dev_dbg(gfb->dev, "waiting for LCD idle: "); */
+ timeout = 200000;
while ((!reg_read(gfb, GLAMO_REG_LCD_STATUS2) & (1 << 12)) &&
(timeout--))
yield();
@@ -585,11 +610,11 @@ void glamofb_cmd_mode(struct glamofb_handle *gfb, int on)
printk(KERN_ERR"*************"
"glamofb lcd never idle"
"*************\n");
- return;
+ return -EIO;
}
- dev_dbg(gfb->dev, "idle!\n");
+/* dev_dbg(gfb->dev, "idle!\n"); */
- msleep(90);
+ mdelay(100);
} else {
/* RGB interface needs vsync/hsync */
if (reg_read(gfb, GLAMO_REG_LCD_MODE3) & GLAMO_LCD_MODE3_RGB)
@@ -601,15 +626,17 @@ void glamofb_cmd_mode(struct glamofb_handle *gfb, int on)
GLAMO_LCD_CMD_TYPE_DISP |
GLAMO_LCD_CMD_DATA_DISP_FIRE);
}
+
+ return 0;
}
EXPORT_SYMBOL_GPL(glamofb_cmd_mode);
int glamofb_cmd_write(struct glamofb_handle *gfb, u_int16_t val)
{
- int timeout = 20000;
+ int timeout = 200000;
- dev_dbg(gfb->dev, "%s: waiting for cmdq empty\n",
- __FUNCTION__);
+/* dev_dbg(gfb->dev, "%s: waiting for cmdq empty\n",
+ __FUNCTION__); */
while ((!glamofb_cmdq_empty(gfb)) && (timeout--))
yield();
if (timeout < 0) {
@@ -618,7 +645,7 @@ int glamofb_cmd_write(struct glamofb_handle *gfb, u_int16_t val)
"*************\n");
return 1;
}
- dev_dbg(gfb->dev, "idle, writing 0x%04x\n", val);
+/* dev_dbg(gfb->dev, "idle, writing 0x%04x\n", val); */
reg_write(gfb, GLAMO_REG_LCD_COMMAND1, val);
@@ -758,6 +785,9 @@ static int __init glamofb_probe(struct platform_device *pdev)
glamo_engine_enable(mach_info->glamo, GLAMO_ENGINE_LCD);
glamo_engine_reset(mach_info->glamo, GLAMO_ENGINE_LCD);
+
+ printk(KERN_ERR"spin_lock_init\n");
+ spin_lock_init(&glamofb->lock_cmd);
glamofb_init_regs(glamofb);
rc = register_framebuffer(fbinfo);
diff --git a/include/linux/glamofb.h b/include/linux/glamofb.h
index 75eefef..51bf593 100644
--- a/include/linux/glamofb.h
+++ b/include/linux/glamofb.h
@@ -33,7 +33,7 @@ struct glamofb_platform_data {
int (*glamo_irq_is_wired)(void);
};
-void glamofb_cmd_mode(struct glamofb_handle *gfb, int on);
+int glamofb_cmd_mode(struct glamofb_handle *gfb, int on);
int glamofb_cmd_write(struct glamofb_handle *gfb, u_int16_t val);
void glamo_lcm_reset(int level);
--
1.5.6.3
|