diff options
Diffstat (limited to 'firmware/target/arm/s5l8700/ipodnano2g/lcd-nano2g.c')
-rw-r--r-- | firmware/target/arm/s5l8700/ipodnano2g/lcd-nano2g.c | 1693 |
1 files changed, 847 insertions, 846 deletions
diff --git a/firmware/target/arm/s5l8700/ipodnano2g/lcd-nano2g.c b/firmware/target/arm/s5l8700/ipodnano2g/lcd-nano2g.c index f2d0c3458f..0f7fbd2cc7 100644 --- a/firmware/target/arm/s5l8700/ipodnano2g/lcd-nano2g.c +++ b/firmware/target/arm/s5l8700/ipodnano2g/lcd-nano2g.c | |||
@@ -1,854 +1,855 @@ | |||
1 | /*************************************************************************** | 1 | /*************************************************************************** |
2 | * __________ __ ___. | 2 | * __________ __ ___. |
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
7 | * \/ \/ \/ \/ \/ | 7 | * \/ \/ \/ \/ \/ |
8 | * $Id$ | 8 | * $Id$ |
9 | * | 9 | * |
10 | * Copyright (C) 2009 by Dave Chapman | 10 | * Copyright (C) 2009 by Dave Chapman |
11 | * | 11 | * |
12 | * This program is free software; you can redistribute it and/or | 12 | * This program is free software; you can redistribute it and/or |
13 | * modify it under the terms of the GNU General Public License | 13 | * modify it under the terms of the GNU General Public License |
14 | * as published by the Free Software Foundation; either version 2 | 14 | * as published by the Free Software Foundation; either version 2 |
15 | * of the License, or (at your option) any later version. | 15 | * of the License, or (at your option) any later version. |
16 | * | 16 | * |
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | 17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
18 | * KIND, either express or implied. | 18 | * KIND, either express or implied. |
19 | * | 19 | * |
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | #include "config.h" | 21 | #include "config.h" |
22 | 22 | ||
23 | #include "hwcompat.h" | 23 | #include "hwcompat.h" |
24 | #include "kernel.h" | 24 | #include "kernel.h" |
25 | #include "lcd.h" | 25 | #include "lcd.h" |
26 | #include "system.h" | 26 | #include "system.h" |
27 | #include "cpu.h" | 27 | #include "cpu.h" |
28 | #include "pmu-target.h" | 28 | #include "pmu-target.h" |
29 | 29 | ||
30 | 30 | ||
31 | /* The Nano 2G has two different LCD types. What we call "type 0" | 31 | /* The Nano 2G has two different LCD types. What we call "type 0" |
32 | appears to be similar to the ILI9320 and "type 1" is similar to the | 32 | appears to be similar to the ILI9320 and "type 1" is similar to the |
33 | LDS176. | 33 | LDS176. |
34 | */ | 34 | */ |
35 | 35 | ||
36 | /* LCD type 0 register defines */ | 36 | /* LCD type 0 register defines */ |
37 | 37 | ||
38 | #define R_ENTRY_MODE 0x03 | 38 | #define R_ENTRY_MODE 0x03 |
39 | #define R_DISPLAY_CONTROL_1 0x07 | 39 | #define R_DISPLAY_CONTROL_1 0x07 |
40 | #define R_POWER_CONTROL_1 0x10 | 40 | #define R_POWER_CONTROL_1 0x10 |
41 | #define R_POWER_CONTROL_2 0x12 | 41 | #define R_POWER_CONTROL_2 0x12 |
42 | #define R_POWER_CONTROL_3 0x13 | 42 | #define R_POWER_CONTROL_3 0x13 |
43 | #define R_HORIZ_GRAM_ADDR_SET 0x20 | 43 | #define R_HORIZ_GRAM_ADDR_SET 0x20 |
44 | #define R_VERT_GRAM_ADDR_SET 0x21 | 44 | #define R_VERT_GRAM_ADDR_SET 0x21 |
45 | #define R_WRITE_DATA_TO_GRAM 0x22 | 45 | #define R_WRITE_DATA_TO_GRAM 0x22 |
46 | #define R_HORIZ_ADDR_START_POS 0x50 | 46 | #define R_HORIZ_ADDR_START_POS 0x50 |
47 | #define R_HORIZ_ADDR_END_POS 0x51 | 47 | #define R_HORIZ_ADDR_END_POS 0x51 |
48 | #define R_VERT_ADDR_START_POS 0x52 | 48 | #define R_VERT_ADDR_START_POS 0x52 |
49 | #define R_VERT_ADDR_END_POS 0x53 | 49 | #define R_VERT_ADDR_END_POS 0x53 |
50 | 50 | ||
51 | 51 | ||
52 | /* LCD type 1 register defines */ | 52 | /* LCD type 1 register defines */ |
53 | 53 | ||
54 | #define R_SLEEP_IN 0x10 | 54 | #define R_SLEEP_IN 0x10 |
55 | #define R_DISPLAY_OFF 0x28 | 55 | #define R_DISPLAY_OFF 0x28 |
56 | #define R_COLUMN_ADDR_SET 0x2a | 56 | #define R_COLUMN_ADDR_SET 0x2a |
57 | #define R_ROW_ADDR_SET 0x2b | 57 | #define R_ROW_ADDR_SET 0x2b |
58 | #define R_MEMORY_WRITE 0x2c | 58 | #define R_MEMORY_WRITE 0x2c |
59 | 59 | ||
60 | /** globals **/ | 60 | /** globals **/ |
61 | 61 | ||
62 | int lcd_type; /* also needed in debug-s5l8700.c */ | 62 | int lcd_type; /* also needed in debug-s5l8700.c */ |
63 | static int xoffset; /* needed for flip */ | 63 | static int xoffset; /* needed for flip */ |
64 | static bool lcd_ispowered; | 64 | static bool lcd_ispowered; |
65 | 65 | ||
66 | #ifdef HAVE_LCD_SLEEP | 66 | #ifdef HAVE_LCD_SLEEP |
67 | 67 | ||
68 | #define SLEEP 0 | 68 | #define SLEEP 0 |
69 | #define CMD8 1 | 69 | #define CMD8 1 |
70 | #define CMD16 2 | 70 | #define CMD16 2 |
71 | #define DATA8 3 | 71 | #define DATA8 3 |
72 | #define DATA16 4 | 72 | #define DATA16 4 |
73 | 73 | ||
74 | unsigned short lcd_init_sequence_0[] = { | 74 | unsigned short lcd_init_sequence_0[] = { |
75 | CMD16, 0x00a4, | 75 | CMD16, 0x00a4, |
76 | DATA16, 0x0001, | 76 | DATA16, 0x0001, |
77 | SLEEP, 0x0000, | 77 | SLEEP, 0x0000, |
78 | CMD16, 0x0001, | 78 | CMD16, 0x0001, |
79 | DATA16, 0x0100, | 79 | DATA16, 0x0100, |
80 | CMD16, 0x0002, | 80 | CMD16, 0x0002, |
81 | DATA16, 0x0300, | 81 | DATA16, 0x0300, |
82 | CMD16, 0x0003, | 82 | CMD16, 0x0003, |
83 | DATA16, 0x1230, | 83 | DATA16, 0x1230, |
84 | CMD16, 0x0008, | 84 | CMD16, 0x0008, |
85 | DATA16, 0x0404, | 85 | DATA16, 0x0404, |
86 | CMD16, 0x0008, | 86 | CMD16, 0x0008, |
87 | DATA16, 0x0404, | 87 | DATA16, 0x0404, |
88 | CMD16, 0x000e, | 88 | CMD16, 0x000e, |
89 | DATA16, 0x0010, | 89 | DATA16, 0x0010, |
90 | CMD16, 0x0070, | 90 | CMD16, 0x0070, |
91 | DATA16, 0x1000, | 91 | DATA16, 0x1000, |
92 | CMD16, 0x0071, | 92 | CMD16, 0x0071, |
93 | DATA16, 0x0001, | 93 | DATA16, 0x0001, |
94 | CMD16, 0x0030, | 94 | CMD16, 0x0030, |
95 | DATA16, 0x0002, | 95 | DATA16, 0x0002, |
96 | CMD16, 0x0031, | 96 | CMD16, 0x0031, |
97 | DATA16, 0x0400, | 97 | DATA16, 0x0400, |
98 | CMD16, 0x0032, | 98 | CMD16, 0x0032, |
99 | DATA16, 0x0007, | 99 | DATA16, 0x0007, |
100 | CMD16, 0x0033, | 100 | CMD16, 0x0033, |
101 | DATA16, 0x0500, | 101 | DATA16, 0x0500, |
102 | CMD16, 0x0034, | 102 | CMD16, 0x0034, |
103 | DATA16, 0x0007, | 103 | DATA16, 0x0007, |
104 | CMD16, 0x0035, | 104 | CMD16, 0x0035, |
105 | DATA16, 0x0703, | 105 | DATA16, 0x0703, |
106 | CMD16, 0x0036, | 106 | CMD16, 0x0036, |
107 | DATA16, 0x0507, | 107 | DATA16, 0x0507, |
108 | CMD16, 0x0037, | 108 | CMD16, 0x0037, |
109 | DATA16, 0x0005, | 109 | DATA16, 0x0005, |
110 | CMD16, 0x0038, | 110 | CMD16, 0x0038, |
111 | DATA16, 0x0407, | 111 | DATA16, 0x0407, |
112 | CMD16, 0x0039, | 112 | CMD16, 0x0039, |
113 | DATA16, 0x000e, | 113 | DATA16, 0x000e, |
114 | CMD16, 0x0040, | 114 | CMD16, 0x0040, |
115 | DATA16, 0x0202, | 115 | DATA16, 0x0202, |
116 | CMD16, 0x0041, | 116 | CMD16, 0x0041, |
117 | DATA16, 0x0003, | 117 | DATA16, 0x0003, |
118 | CMD16, 0x0042, | 118 | CMD16, 0x0042, |
119 | DATA16, 0x0000, | 119 | DATA16, 0x0000, |
120 | CMD16, 0x0043, | 120 | CMD16, 0x0043, |
121 | DATA16, 0x0200, | 121 | DATA16, 0x0200, |
122 | CMD16, 0x0044, | 122 | CMD16, 0x0044, |
123 | DATA16, 0x0707, | 123 | DATA16, 0x0707, |
124 | CMD16, 0x0045, | 124 | CMD16, 0x0045, |
125 | DATA16, 0x0407, | 125 | DATA16, 0x0407, |
126 | CMD16, 0x0046, | 126 | CMD16, 0x0046, |
127 | DATA16, 0x0505, | 127 | DATA16, 0x0505, |
128 | CMD16, 0x0047, | 128 | CMD16, 0x0047, |
129 | DATA16, 0x0002, | 129 | DATA16, 0x0002, |
130 | CMD16, 0x0048, | 130 | CMD16, 0x0048, |
131 | DATA16, 0x0004, | 131 | DATA16, 0x0004, |
132 | CMD16, 0x0049, | 132 | CMD16, 0x0049, |
133 | DATA16, 0x0004, | 133 | DATA16, 0x0004, |
134 | CMD16, 0x0060, | 134 | CMD16, 0x0060, |
135 | DATA16, 0x0202, | 135 | DATA16, 0x0202, |
136 | CMD16, 0x0061, | 136 | CMD16, 0x0061, |
137 | DATA16, 0x0003, | 137 | DATA16, 0x0003, |
138 | CMD16, 0x0062, | 138 | CMD16, 0x0062, |
139 | DATA16, 0x0000, | 139 | DATA16, 0x0000, |
140 | CMD16, 0x0063, | 140 | CMD16, 0x0063, |
141 | DATA16, 0x0200, | 141 | DATA16, 0x0200, |
142 | CMD16, 0x0064, | 142 | CMD16, 0x0064, |
143 | DATA16, 0x0707, | 143 | DATA16, 0x0707, |
144 | CMD16, 0x0065, | 144 | CMD16, 0x0065, |
145 | DATA16, 0x0407, | 145 | DATA16, 0x0407, |
146 | CMD16, 0x0066, | 146 | CMD16, 0x0066, |
147 | DATA16, 0x0505, | 147 | DATA16, 0x0505, |
148 | CMD16, 0x0068, | 148 | CMD16, 0x0068, |
149 | DATA16, 0x0004, | 149 | DATA16, 0x0004, |
150 | CMD16, 0x0069, | 150 | CMD16, 0x0069, |
151 | DATA16, 0x0004, | 151 | DATA16, 0x0004, |
152 | CMD16, 0x0007, | 152 | CMD16, 0x0007, |
153 | DATA16, 0x0001, | 153 | DATA16, 0x0001, |
154 | CMD16, 0x0018, | 154 | CMD16, 0x0018, |
155 | DATA16, 0x0001, | 155 | DATA16, 0x0001, |
156 | CMD16, 0x0010, | 156 | CMD16, 0x0010, |
157 | DATA16, 0x1690, | 157 | DATA16, 0x1690, |
158 | CMD16, 0x0011, | 158 | CMD16, 0x0011, |
159 | DATA16, 0x0100, | 159 | DATA16, 0x0100, |
160 | CMD16, 0x0012, | 160 | CMD16, 0x0012, |
161 | DATA16, 0x0117, | 161 | DATA16, 0x0117, |
162 | CMD16, 0x0013, | 162 | CMD16, 0x0013, |
163 | DATA16, 0x0f80, | 163 | DATA16, 0x0f80, |
164 | CMD16, 0x0012, | 164 | CMD16, 0x0012, |
165 | DATA16, 0x0137, | 165 | DATA16, 0x0137, |
166 | CMD16, 0x0020, | 166 | CMD16, 0x0020, |
167 | DATA16, 0x0000, | 167 | DATA16, 0x0000, |
168 | CMD16, 0x0021, | 168 | CMD16, 0x0021, |
169 | DATA16, 0x0000, | 169 | DATA16, 0x0000, |
170 | CMD16, 0x0050, | 170 | CMD16, 0x0050, |
171 | DATA16, 0x0000, | 171 | DATA16, 0x0000, |
172 | CMD16, 0x0051, | 172 | CMD16, 0x0051, |
173 | DATA16, 0x00af, | 173 | DATA16, 0x00af, |
174 | CMD16, 0x0052, | 174 | CMD16, 0x0052, |
175 | DATA16, 0x0000, | 175 | DATA16, 0x0000, |
176 | CMD16, 0x0053, | 176 | CMD16, 0x0053, |
177 | DATA16, 0x0083, | 177 | DATA16, 0x0083, |
178 | CMD16, 0x0090, | 178 | CMD16, 0x0090, |
179 | DATA16, 0x0003, | 179 | DATA16, 0x0003, |
180 | CMD16, 0x0091, | 180 | CMD16, 0x0091, |
181 | DATA16, 0x0000, | 181 | DATA16, 0x0000, |
182 | CMD16, 0x0092, | 182 | CMD16, 0x0092, |
183 | DATA16, 0x0101, | 183 | DATA16, 0x0101, |
184 | CMD16, 0x0098, | 184 | CMD16, 0x0098, |
185 | DATA16, 0x0400, | 185 | DATA16, 0x0400, |
186 | CMD16, 0x0099, | 186 | CMD16, 0x0099, |
187 | DATA16, 0x1302, | 187 | DATA16, 0x1302, |
188 | CMD16, 0x009a, | 188 | CMD16, 0x009a, |
189 | DATA16, 0x0202, | 189 | DATA16, 0x0202, |
190 | CMD16, 0x009b, | 190 | CMD16, 0x009b, |
191 | DATA16, 0x0200, | 191 | DATA16, 0x0200, |
192 | SLEEP, 0x0000, | 192 | SLEEP, 0x0000, |
193 | CMD16, 0x0007, | 193 | CMD16, 0x0007, |
194 | DATA16, 0x0021, | 194 | DATA16, 0x0021, |
195 | CMD16, 0x0012, | 195 | CMD16, 0x0012, |
196 | DATA16, 0x0137, | 196 | DATA16, 0x0137, |
197 | SLEEP, 0x0000, | 197 | SLEEP, 0x0000, |
198 | CMD16, 0x0007, | 198 | CMD16, 0x0007, |
199 | DATA16, 0x0021, | 199 | DATA16, 0x0021, |
200 | CMD16, 0x0012, | 200 | CMD16, 0x0012, |
201 | DATA16, 0x1137, | 201 | DATA16, 0x1137, |
202 | SLEEP, 0x0000, | 202 | SLEEP, 0x0000, |
203 | CMD16, 0x0007, | 203 | CMD16, 0x0007, |
204 | DATA16, 0x0233, | 204 | DATA16, 0x0233, |
205 | }; | 205 | }; |
206 | 206 | ||
207 | unsigned short lcd_init_sequence_1[] = { | 207 | unsigned short lcd_init_sequence_1[] = { |
208 | CMD8, 0x01, | 208 | CMD8, 0x01, |
209 | DATA8, 0x00, | 209 | DATA8, 0x00, |
210 | SLEEP, 0, | 210 | SLEEP, 0, |
211 | CMD8, 0xB1, | 211 | CMD8, 0xB1, |
212 | DATA8, 0x16, | 212 | DATA8, 0x16, |
213 | DATA8, 0x03, | 213 | DATA8, 0x03, |
214 | CMD8, 0xB2, | 214 | CMD8, 0xB2, |
215 | DATA8, 0x17, | 215 | DATA8, 0x17, |
216 | DATA8, 0x03, | 216 | DATA8, 0x03, |
217 | CMD8, 0xB4, | 217 | CMD8, 0xB4, |
218 | DATA8, 0x00, | 218 | DATA8, 0x00, |
219 | CMD8, 0xB6, | 219 | CMD8, 0xB6, |
220 | DATA8, 0x01, | 220 | DATA8, 0x01, |
221 | CMD8, 0xB7, | 221 | CMD8, 0xB7, |
222 | DATA8, 0x00, | 222 | DATA8, 0x00, |
223 | DATA8, 0x00, | 223 | DATA8, 0x00, |
224 | DATA8, 0x02, | 224 | DATA8, 0x02, |
225 | DATA8, 0x00, | 225 | DATA8, 0x00, |
226 | DATA8, 0x06, | 226 | DATA8, 0x06, |
227 | DATA8, 0x26, | 227 | DATA8, 0x26, |
228 | DATA8, 0x2D, | 228 | DATA8, 0x2D, |
229 | DATA8, 0x27, | 229 | DATA8, 0x27, |
230 | DATA8, 0x55, | 230 | DATA8, 0x55, |
231 | DATA8, 0x27, | 231 | DATA8, 0x27, |
232 | CMD8, 0xB8, | 232 | CMD8, 0xB8, |
233 | DATA8, 0x10, | 233 | DATA8, 0x10, |
234 | CMD8, 0xB9, | 234 | CMD8, 0xB9, |
235 | DATA8, 0x52, | 235 | DATA8, 0x52, |
236 | DATA8, 0x12, | 236 | DATA8, 0x12, |
237 | DATA8, 0x03, | 237 | DATA8, 0x03, |
238 | CMD8, 0xC0, | 238 | CMD8, 0xC0, |
239 | DATA8, 0x0A, | 239 | DATA8, 0x0A, |
240 | DATA8, 0x10, | 240 | DATA8, 0x10, |
241 | DATA8, 0x10, | 241 | DATA8, 0x10, |
242 | CMD8, 0xC2, | 242 | CMD8, 0xC2, |
243 | DATA8, 0x14, | 243 | DATA8, 0x14, |
244 | DATA8, 0x23, | 244 | DATA8, 0x23, |
245 | CMD8, 0xC3, | 245 | CMD8, 0xC3, |
246 | DATA8, 0x12, | 246 | DATA8, 0x12, |
247 | DATA8, 0x23, | 247 | DATA8, 0x23, |
248 | CMD8, 0xC6, | 248 | CMD8, 0xC6, |
249 | DATA8, 0x48, | 249 | DATA8, 0x48, |
250 | CMD8, 0xE0, | 250 | CMD8, 0xE0, |
251 | DATA8, 0x20, | 251 | DATA8, 0x20, |
252 | DATA8, 0x71, | 252 | DATA8, 0x71, |
253 | DATA8, 0x17, | 253 | DATA8, 0x17, |
254 | DATA8, 0x09, | 254 | DATA8, 0x09, |
255 | DATA8, 0x70, | 255 | DATA8, 0x70, |
256 | DATA8, 0x0C, | 256 | DATA8, 0x0C, |
257 | DATA8, 0x13, | 257 | DATA8, 0x13, |
258 | DATA8, 0x25, | 258 | DATA8, 0x25, |
259 | CMD8, 0xE1, | 259 | CMD8, 0xE1, |
260 | DATA8, 0x37, | 260 | DATA8, 0x37, |
261 | DATA8, 0x00, | 261 | DATA8, 0x00, |
262 | DATA8, 0x63, | 262 | DATA8, 0x63, |
263 | DATA8, 0x11, | 263 | DATA8, 0x11, |
264 | DATA8, 0xD9, | 264 | DATA8, 0xD9, |
265 | DATA8, 0x00, | 265 | DATA8, 0x00, |
266 | DATA8, 0x12, | 266 | DATA8, 0x12, |
267 | DATA8, 0x01, | 267 | DATA8, 0x01, |
268 | CMD8, 0xE2, | 268 | CMD8, 0xE2, |
269 | DATA8, 0x42, | 269 | DATA8, 0x42, |
270 | DATA8, 0x42, | 270 | DATA8, 0x42, |
271 | DATA8, 0x60, | 271 | DATA8, 0x60, |
272 | DATA8, 0x08, | 272 | DATA8, 0x08, |
273 | DATA8, 0xB4, | 273 | DATA8, 0xB4, |
274 | DATA8, 0x07, | 274 | DATA8, 0x07, |
275 | DATA8, 0x0E, | 275 | DATA8, 0x0E, |
276 | DATA8, 0x90, | 276 | DATA8, 0x90, |
277 | CMD8, 0xE3, | 277 | CMD8, 0xE3, |
278 | DATA8, 0x47, | 278 | DATA8, 0x47, |
279 | DATA8, 0x60, | 279 | DATA8, 0x60, |
280 | DATA8, 0x66, | 280 | DATA8, 0x66, |
281 | DATA8, 0x09, | 281 | DATA8, 0x09, |
282 | DATA8, 0x6A, | 282 | DATA8, 0x6A, |
283 | DATA8, 0x02, | 283 | DATA8, 0x02, |
284 | DATA8, 0x0E, | 284 | DATA8, 0x0E, |
285 | DATA8, 0x09, | 285 | DATA8, 0x09, |
286 | CMD8, 0xE4, | 286 | CMD8, 0xE4, |
287 | DATA8, 0x11, | 287 | DATA8, 0x11, |
288 | DATA8, 0x40, | 288 | DATA8, 0x40, |
289 | DATA8, 0x03, | 289 | DATA8, 0x03, |
290 | DATA8, 0x0A, | 290 | DATA8, 0x0A, |
291 | DATA8, 0xC1, | 291 | DATA8, 0xC1, |
292 | DATA8, 0x0D, | 292 | DATA8, 0x0D, |
293 | DATA8, 0x17, | 293 | DATA8, 0x17, |
294 | DATA8, 0x30, | 294 | DATA8, 0x30, |
295 | CMD8, 0xE5, | 295 | CMD8, 0xE5, |
296 | DATA8, 0x00, | 296 | DATA8, 0x00, |
297 | DATA8, 0x30, | 297 | DATA8, 0x30, |
298 | DATA8, 0x77, | 298 | DATA8, 0x77, |
299 | DATA8, 0x1C, | 299 | DATA8, 0x1C, |
300 | DATA8, 0xFB, | 300 | DATA8, 0xFB, |
301 | DATA8, 0x00, | 301 | DATA8, 0x00, |
302 | DATA8, 0x13, | 302 | DATA8, 0x13, |
303 | DATA8, 0x07, | 303 | DATA8, 0x07, |
304 | CMD8, 0xE6, | 304 | CMD8, 0xE6, |
305 | DATA8, 0x01, | 305 | DATA8, 0x01, |
306 | CMD8, 0x35, | 306 | CMD8, 0x35, |
307 | DATA8, 0x00, | 307 | DATA8, 0x00, |
308 | CMD8, 0x36, | 308 | CMD8, 0x36, |
309 | DATA8, 0x00, | 309 | DATA8, 0x00, |
310 | CMD8, 0xF2, | 310 | CMD8, 0xF2, |
311 | DATA8, 0x40, | 311 | DATA8, 0x40, |
312 | CMD8, 0xF3, | 312 | CMD8, 0xF3, |
313 | DATA8, 0x50, | 313 | DATA8, 0x50, |
314 | CMD8, 0xFB, | 314 | CMD8, 0xFB, |
315 | DATA8, 0x01, | 315 | DATA8, 0x01, |
316 | CMD8, 0x11, | 316 | CMD8, 0x11, |
317 | DATA8, 0x00, | 317 | DATA8, 0x00, |
318 | SLEEP, 0, | 318 | SLEEP, 0, |
319 | CMD8, 0x3A, | 319 | CMD8, 0x3A, |
320 | DATA8, 0x65, | 320 | DATA8, 0x65, |
321 | CMD8, 0x29, | 321 | CMD8, 0x29, |
322 | DATA8, 0x00, | 322 | DATA8, 0x00, |
323 | }; | 323 | }; |
324 | 324 | ||
325 | unsigned short lcd_init_sequence_2[] = { | 325 | unsigned short lcd_init_sequence_2[] = { |
326 | CMD8, 0x01, | 326 | CMD8, 0x01, |
327 | SLEEP, 0, | 327 | SLEEP, 0, |
328 | CMD8, 0x11, | 328 | CMD8, 0x11, |
329 | SLEEP, 0, | 329 | SLEEP, 0, |
330 | CMD8, 0x3a, | 330 | CMD8, 0x3a, |
331 | DATA8, 0x65, | 331 | DATA8, 0x65, |
332 | CMD8, 0xab, | 332 | CMD8, 0xab, |
333 | CMD8, 0x35, | 333 | CMD8, 0x35, |
334 | DATA8, 0x00, | 334 | DATA8, 0x00, |
335 | CMD8, 0xf2, | 335 | CMD8, 0xf2, |
336 | DATA8, 0x01, | 336 | DATA8, 0x01, |
337 | CMD8, 0xe0, | 337 | CMD8, 0xe0, |
338 | DATA8, 0x71, | 338 | DATA8, 0x71, |
339 | DATA8, 0x76, | 339 | DATA8, 0x76, |
340 | DATA8, 0x25, | 340 | DATA8, 0x25, |
341 | DATA8, 0x01, | 341 | DATA8, 0x01, |
342 | DATA8, 0xa5, | 342 | DATA8, 0xa5, |
343 | DATA8, 0x09, | 343 | DATA8, 0x09, |
344 | DATA8, 0x15, | 344 | DATA8, 0x15, |
345 | DATA8, 0x11, | 345 | DATA8, 0x11, |
346 | CMD8, 0xe1, | 346 | CMD8, 0xe1, |
347 | DATA8, 0x40, | 347 | DATA8, 0x40, |
348 | DATA8, 0x21, | 348 | DATA8, 0x21, |
349 | DATA8, 0x64, | 349 | DATA8, 0x64, |
350 | DATA8, 0x13, | 350 | DATA8, 0x13, |
351 | DATA8, 0xf3, | 351 | DATA8, 0xf3, |
352 | DATA8, 0x0b, | 352 | DATA8, 0x0b, |
353 | DATA8, 0x00, | 353 | DATA8, 0x00, |
354 | DATA8, 0x00, | 354 | DATA8, 0x00, |
355 | CMD8, 0xe2, | 355 | CMD8, 0xe2, |
356 | DATA8, 0x71, | 356 | DATA8, 0x71, |
357 | DATA8, 0x65, | 357 | DATA8, 0x65, |
358 | DATA8, 0x24, | 358 | DATA8, 0x24, |
359 | DATA8, 0x08, | 359 | DATA8, 0x08, |
360 | DATA8, 0x97, | 360 | DATA8, 0x97, |
361 | DATA8, 0x01, | 361 | DATA8, 0x01, |
362 | DATA8, 0x15, | 362 | DATA8, 0x15, |
363 | DATA8, 0x11, | 363 | DATA8, 0x11, |
364 | CMD8, 0xe3, | 364 | CMD8, 0xe3, |
365 | DATA8, 0x51, | 365 | DATA8, 0x51, |
366 | DATA8, 0x01, | 366 | DATA8, 0x01, |
367 | DATA8, 0x62, | 367 | DATA8, 0x62, |
368 | DATA8, 0x13, | 368 | DATA8, 0x13, |
369 | DATA8, 0xf3, | 369 | DATA8, 0xf3, |
370 | DATA8, 0x0b, | 370 | DATA8, 0x0b, |
371 | DATA8, 0x00, | 371 | DATA8, 0x00, |
372 | DATA8, 0x00, | 372 | DATA8, 0x00, |
373 | CMD8, 0xe4, | 373 | CMD8, 0xe4, |
374 | DATA8, 0x71, | 374 | DATA8, 0x71, |
375 | DATA8, 0x57, | 375 | DATA8, 0x57, |
376 | DATA8, 0x31, | 376 | DATA8, 0x31, |
377 | DATA8, 0x01, | 377 | DATA8, 0x01, |
378 | DATA8, 0x82, | 378 | DATA8, 0x82, |
379 | DATA8, 0x04, | 379 | DATA8, 0x04, |
380 | DATA8, 0x1f, | 380 | DATA8, 0x1f, |
381 | DATA8, 0x11, | 381 | DATA8, 0x11, |
382 | CMD8, 0xe5, | 382 | CMD8, 0xe5, |
383 | DATA8, 0x64, | 383 | DATA8, 0x64, |
384 | DATA8, 0x41, | 384 | DATA8, 0x41, |
385 | DATA8, 0x64, | 385 | DATA8, 0x64, |
386 | DATA8, 0x19, | 386 | DATA8, 0x19, |
387 | DATA8, 0xb3, | 387 | DATA8, 0xb3, |
388 | DATA8, 0x09, | 388 | DATA8, 0x09, |
389 | DATA8, 0x00, | 389 | DATA8, 0x00, |
390 | DATA8, 0x00, | 390 | DATA8, 0x00, |
391 | CMD8, 0x29, | 391 | CMD8, 0x29, |
392 | }; | 392 | }; |
393 | 393 | ||
394 | #endif /* HAVE_LCD_SLEEP */ | 394 | #endif /* HAVE_LCD_SLEEP */ |
395 | 395 | ||
396 | static inline void s5l_lcd_write_cmd_data(int cmd, int data) | 396 | static inline void s5l_lcd_write_cmd_data(int cmd, int data) |
397 | { | 397 | { |
398 | while (LCD_STATUS & 0x10); | 398 | while (LCD_STATUS & 0x10); |
399 | LCD_WCMD = cmd >> 8; | 399 | LCD_WCMD = cmd >> 8; |
400 | while (LCD_STATUS & 0x10); | 400 | while (LCD_STATUS & 0x10); |
401 | LCD_WCMD = cmd & 0xff; | 401 | LCD_WCMD = cmd & 0xff; |
402 | 402 | ||
403 | while (LCD_STATUS & 0x10); | 403 | while (LCD_STATUS & 0x10); |
404 | LCD_WDATA = data >> 8; | 404 | LCD_WDATA = data >> 8; |
405 | while (LCD_STATUS & 0x10); | 405 | while (LCD_STATUS & 0x10); |
406 | LCD_WDATA = data & 0xff; | 406 | LCD_WDATA = data & 0xff; |
407 | } | 407 | } |
408 | 408 | ||
409 | static inline void s5l_lcd_write_cmd(unsigned short cmd) | 409 | static inline void s5l_lcd_write_cmd(unsigned short cmd) |
410 | { | 410 | { |
411 | while (LCD_STATUS & 0x10); | 411 | while (LCD_STATUS & 0x10); |
412 | LCD_WCMD = cmd; | 412 | LCD_WCMD = cmd; |
413 | } | 413 | } |
414 | 414 | ||
415 | static inline void s5l_lcd_write_wcmd(unsigned short cmd) | 415 | static inline void s5l_lcd_write_wcmd(unsigned short cmd) |
416 | { | 416 | { |
417 | while (LCD_STATUS & 0x10); | 417 | while (LCD_STATUS & 0x10); |
418 | LCD_WCMD = cmd >> 8; | 418 | LCD_WCMD = cmd >> 8; |
419 | while (LCD_STATUS & 0x10); | 419 | while (LCD_STATUS & 0x10); |
420 | LCD_WCMD = cmd & 0xff; | 420 | LCD_WCMD = cmd & 0xff; |
421 | } | 421 | } |
422 | 422 | ||
423 | static inline void s5l_lcd_write_data(unsigned short data) | 423 | static inline void s5l_lcd_write_data(unsigned short data) |
424 | { | 424 | { |
425 | while (LCD_STATUS & 0x10); | 425 | while (LCD_STATUS & 0x10); |
426 | LCD_WDATA = data & 0xff; | 426 | LCD_WDATA = data & 0xff; |
427 | } | 427 | } |
428 | 428 | ||
429 | static inline void s5l_lcd_write_wdata(unsigned short data) | 429 | static inline void s5l_lcd_write_wdata(unsigned short data) |
430 | { | 430 | { |
431 | while (LCD_STATUS & 0x10); | 431 | while (LCD_STATUS & 0x10); |
432 | LCD_WDATA = data >> 8; | 432 | LCD_WDATA = data >> 8; |
433 | while (LCD_STATUS & 0x10); | 433 | while (LCD_STATUS & 0x10); |
434 | LCD_WDATA = data & 0xff; | 434 | LCD_WDATA = data & 0xff; |
435 | } | 435 | } |
436 | 436 | ||
437 | /*** hardware configuration ***/ | 437 | /*** hardware configuration ***/ |
438 | 438 | ||
439 | int lcd_default_contrast(void) | 439 | int lcd_default_contrast(void) |
440 | { | 440 | { |
441 | return 0x1f; | 441 | return 0x1f; |
442 | } | 442 | } |
443 | 443 | ||
444 | void lcd_set_contrast(int val) | 444 | void lcd_set_contrast(int val) |
445 | { | 445 | { |
446 | (void)val; | 446 | (void)val; |
447 | } | 447 | } |
448 | 448 | ||
449 | void lcd_set_invert_display(bool yesno) | 449 | void lcd_set_invert_display(bool yesno) |
450 | { | 450 | { |
451 | (void)yesno; | 451 | (void)yesno; |
452 | } | 452 | } |
453 | 453 | ||
454 | /* turn the display upside down (call lcd_update() afterwards) */ | 454 | /* turn the display upside down (call lcd_update() afterwards) */ |
455 | void lcd_set_flip(bool yesno) | 455 | void lcd_set_flip(bool yesno) |
456 | { | 456 | { |
457 | /* TODO: flip mode isn't working. The commands in the else part of | 457 | /* TODO: flip mode isn't working. The commands in the else part of |
458 | this function are how the original firmware inits the LCD */ | 458 | this function are how the original firmware inits the LCD */ |
459 | 459 | ||
460 | if (yesno) | 460 | if (yesno) |
461 | { | 461 | { |
462 | xoffset = 132 - LCD_WIDTH; /* 132 colums minus the 128 we have */ | 462 | xoffset = 132 - LCD_WIDTH; /* 132 colums minus the 128 we have */ |
463 | } | 463 | } |
464 | else | 464 | else |
465 | { | 465 | { |
466 | xoffset = 0; | 466 | xoffset = 0; |
467 | } | 467 | } |
468 | } | 468 | } |
469 | 469 | ||
470 | bool lcd_active(void) | 470 | bool lcd_active(void) |
471 | { | 471 | { |
472 | return lcd_ispowered; | 472 | return lcd_ispowered; |
473 | } | 473 | } |
474 | 474 | ||
475 | #ifdef HAVE_LCD_SLEEP | 475 | #ifdef HAVE_LCD_SLEEP |
476 | 476 | ||
477 | void lcd_wakeup(void) | 477 | void lcd_wakeup(void) |
478 | { | 478 | { |
479 | unsigned short *lcd_init_sequence; | 479 | unsigned short *lcd_init_sequence; |
480 | unsigned int lcd_init_sequence_length; | 480 | unsigned int lcd_init_sequence_length; |
481 | int type = lcd_type; | 481 | int type = lcd_type; |
482 | 482 | ||
483 | pmu_ldo_set_voltage(2, 17); | 483 | pmu_ldo_set_voltage(2, 17); |
484 | PWRCONEXT &= ~0x80; | 484 | PWRCONEXT &= ~0x80; |
485 | PCON2 = 0x33333333; | 485 | PCON2 = 0x33333333; |
486 | PCON3 = 0x11113333; | 486 | PCON3 = 0x11113333; |
487 | PCON4 = 0x33333333; | 487 | PCON4 = 0x33333333; |
488 | PCON13 &= ~0xf; /* Set pin 0 to input */ | 488 | PCON13 &= ~0xf; /* Set pin 0 to input */ |
489 | PCON14 &= ~0xf0; /* Set pin 1 to input */ | 489 | PCON14 &= ~0xf0; /* Set pin 1 to input */ |
490 | 490 | ||
491 | if((((PDAT13 & 1) == 1) && ((PDAT14 & 2) == 2))|| | 491 | if((((PDAT13 & 1) == 1) && ((PDAT14 & 2) == 2))|| |
492 | (((PDAT13 & 1) == 0) && ((PDAT14 & 2) == 0))) | 492 | (((PDAT13 & 1) == 0) && ((PDAT14 & 2) == 0))) |
493 | { | 493 | { |
494 | type = 2; /* there is a third lcd type which behaves like type 7 (LDS176) but needs to be initialized differently */ | 494 | type = 2; /* there is a third lcd type which behaves like type 7 (LDS176) but needs to be initialized differently */ |
495 | } | 495 | } |
496 | 496 | ||
497 | if(type == 0) | 497 | if(type == 0) |
498 | { | 498 | { |
499 | lcd_init_sequence = lcd_init_sequence_0; | 499 | lcd_init_sequence = lcd_init_sequence_0; |
500 | lcd_init_sequence_length = (sizeof(lcd_init_sequence_0) - 1)/sizeof(unsigned short); | 500 | lcd_init_sequence_length = (sizeof(lcd_init_sequence_0) - 1)/sizeof(unsigned short); |
501 | } | 501 | } |
502 | else if(type == 1) | 502 | else if(type == 1) |
503 | { | 503 | { |
504 | lcd_init_sequence = lcd_init_sequence_1; | 504 | lcd_init_sequence = lcd_init_sequence_1; |
505 | lcd_init_sequence_length = (sizeof(lcd_init_sequence_1) - 1)/sizeof(unsigned short); | 505 | lcd_init_sequence_length = (sizeof(lcd_init_sequence_1) - 1)/sizeof(unsigned short); |
506 | } | 506 | } |
507 | else | 507 | else |
508 | { | 508 | { |
509 | lcd_init_sequence = lcd_init_sequence_2; | 509 | lcd_init_sequence = lcd_init_sequence_2; |
510 | lcd_init_sequence_length = (sizeof(lcd_init_sequence_2) - 1)/sizeof(unsigned short); | 510 | lcd_init_sequence_length = (sizeof(lcd_init_sequence_2) - 1)/sizeof(unsigned short); |
511 | } | 511 | } |
512 | 512 | ||
513 | /* reset the lcd chip */ | 513 | /* reset the lcd chip */ |
514 | 514 | ||
515 | LCD_RST_TIME = 0x7FFF; | 515 | LCD_RST_TIME = 0x7FFF; |
516 | LCD_DRV_RST = 0; | 516 | LCD_DRV_RST = 0; |
517 | sleep(0); | 517 | sleep(0); |
518 | LCD_DRV_RST = 1; | 518 | LCD_DRV_RST = 1; |
519 | sleep(HZ / 100); | 519 | sleep(HZ / 100); |
520 | 520 | ||
521 | for(unsigned int i=0;i<lcd_init_sequence_length;i+=2) | 521 | for(unsigned int i=0;i<lcd_init_sequence_length;i+=2) |
522 | { | 522 | { |
523 | switch(lcd_init_sequence[i]) | 523 | switch(lcd_init_sequence[i]) |
524 | { | 524 | { |
525 | case CMD8: | 525 | case CMD8: |
526 | s5l_lcd_write_cmd(lcd_init_sequence[i+1]); | 526 | s5l_lcd_write_cmd(lcd_init_sequence[i+1]); |
527 | break; | 527 | break; |
528 | case DATA8: | 528 | case DATA8: |
529 | s5l_lcd_write_data(lcd_init_sequence[i+1]); | 529 | s5l_lcd_write_data(lcd_init_sequence[i+1]); |
530 | break; | 530 | break; |
531 | case CMD16: | 531 | case CMD16: |
532 | s5l_lcd_write_wcmd(lcd_init_sequence[i+1]); | 532 | s5l_lcd_write_wcmd(lcd_init_sequence[i+1]); |
533 | break; | 533 | break; |
534 | case DATA16: | 534 | case DATA16: |
535 | s5l_lcd_write_wdata(lcd_init_sequence[i+1]); | 535 | s5l_lcd_write_wdata(lcd_init_sequence[i+1]); |
536 | break; | 536 | break; |
537 | case SLEEP: | 537 | case SLEEP: |
538 | sleep(lcd_init_sequence[i+1]); | 538 | sleep(lcd_init_sequence[i+1]); |
539 | break; | 539 | break; |
540 | default: | 540 | default: |
541 | break; | 541 | break; |
542 | } | 542 | } |
543 | } | 543 | } |
544 | lcd_ispowered = true; | 544 | lcd_ispowered = true; |
545 | } | 545 | send_event(LCD_EVENT_ACTIVATION, NULL); |
546 | 546 | } | |
547 | void lcd_awake(void) | 547 | |
548 | { | 548 | void lcd_awake(void) |
549 | if(!lcd_active()) lcd_wakeup(); | 549 | { |
550 | } | 550 | if(!lcd_active()) lcd_wakeup(); |
551 | #endif | 551 | } |
552 | 552 | #endif | |
553 | void lcd_shutdown(void) | 553 | |
554 | { | 554 | void lcd_shutdown(void) |
555 | pmu_write(0x2b, 0); /* Kill the backlight, instantly. */ | 555 | { |
556 | pmu_write(0x29, 0); | 556 | pmu_write(0x2b, 0); /* Kill the backlight, instantly. */ |
557 | 557 | pmu_write(0x29, 0); | |
558 | if (lcd_type == 0) | 558 | |
559 | { | 559 | if (lcd_type == 0) |
560 | s5l_lcd_write_cmd_data(R_DISPLAY_CONTROL_1, 0x232); | 560 | { |
561 | s5l_lcd_write_cmd_data(R_POWER_CONTROL_3, 0x1137); | 561 | s5l_lcd_write_cmd_data(R_DISPLAY_CONTROL_1, 0x232); |
562 | s5l_lcd_write_cmd_data(R_DISPLAY_CONTROL_1, 0x201); | 562 | s5l_lcd_write_cmd_data(R_POWER_CONTROL_3, 0x1137); |
563 | s5l_lcd_write_cmd_data(R_POWER_CONTROL_3, 0x137); | 563 | s5l_lcd_write_cmd_data(R_DISPLAY_CONTROL_1, 0x201); |
564 | s5l_lcd_write_cmd_data(R_DISPLAY_CONTROL_1, 0x200); | 564 | s5l_lcd_write_cmd_data(R_POWER_CONTROL_3, 0x137); |
565 | s5l_lcd_write_cmd_data(R_POWER_CONTROL_1, 0x680); | 565 | s5l_lcd_write_cmd_data(R_DISPLAY_CONTROL_1, 0x200); |
566 | s5l_lcd_write_cmd_data(R_POWER_CONTROL_2, 0x160); | 566 | s5l_lcd_write_cmd_data(R_POWER_CONTROL_1, 0x680); |
567 | s5l_lcd_write_cmd_data(R_POWER_CONTROL_3, 0x127); | 567 | s5l_lcd_write_cmd_data(R_POWER_CONTROL_2, 0x160); |
568 | s5l_lcd_write_cmd_data(R_POWER_CONTROL_1, 0x600); | 568 | s5l_lcd_write_cmd_data(R_POWER_CONTROL_3, 0x127); |
569 | } | 569 | s5l_lcd_write_cmd_data(R_POWER_CONTROL_1, 0x600); |
570 | else | 570 | } |
571 | { | 571 | else |
572 | s5l_lcd_write_cmd(R_DISPLAY_OFF); | 572 | { |
573 | s5l_lcd_write_wdata(0); | 573 | s5l_lcd_write_cmd(R_DISPLAY_OFF); |
574 | s5l_lcd_write_wdata(0); | 574 | s5l_lcd_write_wdata(0); |
575 | s5l_lcd_write_cmd(R_SLEEP_IN); | 575 | s5l_lcd_write_wdata(0); |
576 | s5l_lcd_write_wdata(0); | 576 | s5l_lcd_write_cmd(R_SLEEP_IN); |
577 | s5l_lcd_write_wdata(0); | 577 | s5l_lcd_write_wdata(0); |
578 | } | 578 | s5l_lcd_write_wdata(0); |
579 | 579 | } | |
580 | |||
580 | PCON2 = 0; | 581 | PCON2 = 0; |
581 | PCON3 = 0; | 582 | PCON3 = 0; |
582 | PCON4 = 0; | 583 | PCON4 = 0; |
583 | PWRCONEXT |= 0x80; | 584 | PWRCONEXT |= 0x80; |
584 | sleep(HZ / 20); | 585 | sleep(HZ / 20); |
585 | pmu_ldo_set_voltage(2, 1); | 586 | pmu_ldo_set_voltage(2, 1); |
586 | 587 | ||
587 | lcd_ispowered = false; | 588 | lcd_ispowered = false; |
588 | } | 589 | } |
589 | 590 | ||
590 | void lcd_sleep(void) | 591 | void lcd_sleep(void) |
591 | { | 592 | { |
592 | lcd_shutdown(); | 593 | lcd_shutdown(); |
593 | } | 594 | } |
594 | 595 | ||
595 | /* LCD init */ | 596 | /* LCD init */ |
596 | void lcd_init_device(void) | 597 | void lcd_init_device(void) |
597 | { | 598 | { |
598 | /* Detect lcd type */ | 599 | /* Detect lcd type */ |
599 | 600 | ||
600 | PCON13 &= ~0xf; /* Set pin 0 to input */ | 601 | PCON13 &= ~0xf; /* Set pin 0 to input */ |
601 | PCON14 &= ~0xf0; /* Set pin 1 to input */ | 602 | PCON14 &= ~0xf0; /* Set pin 1 to input */ |
602 | 603 | ||
603 | if (((PDAT13 & 1) == 0) && ((PDAT14 & 2) == 2)) | 604 | if (((PDAT13 & 1) == 0) && ((PDAT14 & 2) == 2)) |
604 | lcd_type = 0; /* Similar to ILI9320 - aka "type 2" */ | 605 | lcd_type = 0; /* Similar to ILI9320 - aka "type 2" */ |
605 | else | 606 | else |
606 | lcd_type = 1; /* Similar to LDS176 - aka "type 7" */ | 607 | lcd_type = 1; /* Similar to LDS176 - aka "type 7" */ |
607 | 608 | ||
608 | lcd_ispowered = true; | 609 | lcd_ispowered = true; |
609 | } | 610 | } |
610 | 611 | ||
611 | /*** Update functions ***/ | 612 | /*** Update functions ***/ |
612 | 613 | ||
613 | static inline void lcd_write_pixel(fb_data pixel) | 614 | static inline void lcd_write_pixel(fb_data pixel) |
614 | { | 615 | { |
615 | while (LCD_STATUS & 0x10); | 616 | while (LCD_STATUS & 0x10); |
616 | LCD_WDATA = (pixel & 0xff00) >> 8; | 617 | LCD_WDATA = (pixel & 0xff00) >> 8; |
617 | while (LCD_STATUS & 0x10); | 618 | while (LCD_STATUS & 0x10); |
618 | LCD_WDATA = pixel & 0xff; | 619 | LCD_WDATA = pixel & 0xff; |
619 | } | 620 | } |
620 | 621 | ||
621 | /* Update the display. | 622 | /* Update the display. |
622 | This must be called after all other LCD functions that change the display. */ | 623 | This must be called after all other LCD functions that change the display. */ |
623 | void lcd_update(void) ICODE_ATTR; | 624 | void lcd_update(void) ICODE_ATTR; |
624 | void lcd_update(void) | 625 | void lcd_update(void) |
625 | { | 626 | { |
626 | int x,y; | 627 | int x,y; |
627 | fb_data* p = &lcd_framebuffer[0][0]; | 628 | fb_data* p = &lcd_framebuffer[0][0]; |
628 | 629 | ||
629 | if (lcd_type==0) { | 630 | if (lcd_type==0) { |
630 | s5l_lcd_write_cmd_data(R_HORIZ_ADDR_START_POS, 0); | 631 | s5l_lcd_write_cmd_data(R_HORIZ_ADDR_START_POS, 0); |
631 | s5l_lcd_write_cmd_data(R_HORIZ_ADDR_END_POS, LCD_WIDTH-1); | 632 | s5l_lcd_write_cmd_data(R_HORIZ_ADDR_END_POS, LCD_WIDTH-1); |
632 | s5l_lcd_write_cmd_data(R_VERT_ADDR_START_POS, 0); | 633 | s5l_lcd_write_cmd_data(R_VERT_ADDR_START_POS, 0); |
633 | s5l_lcd_write_cmd_data(R_VERT_ADDR_END_POS, LCD_HEIGHT-1); | 634 | s5l_lcd_write_cmd_data(R_VERT_ADDR_END_POS, LCD_HEIGHT-1); |
634 | 635 | ||
635 | s5l_lcd_write_cmd_data(R_HORIZ_GRAM_ADDR_SET, 0); | 636 | s5l_lcd_write_cmd_data(R_HORIZ_GRAM_ADDR_SET, 0); |
636 | s5l_lcd_write_cmd_data(R_VERT_GRAM_ADDR_SET, 0); | 637 | s5l_lcd_write_cmd_data(R_VERT_GRAM_ADDR_SET, 0); |
637 | 638 | ||
638 | s5l_lcd_write_cmd(0); | 639 | s5l_lcd_write_cmd(0); |
639 | s5l_lcd_write_cmd(R_WRITE_DATA_TO_GRAM); | 640 | s5l_lcd_write_cmd(R_WRITE_DATA_TO_GRAM); |
640 | } else { | 641 | } else { |
641 | s5l_lcd_write_cmd(R_COLUMN_ADDR_SET); | 642 | s5l_lcd_write_cmd(R_COLUMN_ADDR_SET); |
642 | s5l_lcd_write_wdata(0); /* Start column */ | 643 | s5l_lcd_write_wdata(0); /* Start column */ |
643 | s5l_lcd_write_wdata(LCD_WIDTH-1); /* End column */ | 644 | s5l_lcd_write_wdata(LCD_WIDTH-1); /* End column */ |
644 | 645 | ||
645 | s5l_lcd_write_cmd(R_ROW_ADDR_SET); | 646 | s5l_lcd_write_cmd(R_ROW_ADDR_SET); |
646 | s5l_lcd_write_wdata(0); /* Start row */ | 647 | s5l_lcd_write_wdata(0); /* Start row */ |
647 | s5l_lcd_write_wdata(LCD_HEIGHT-1); /* End row */ | 648 | s5l_lcd_write_wdata(LCD_HEIGHT-1); /* End row */ |
648 | 649 | ||
649 | s5l_lcd_write_cmd(R_MEMORY_WRITE); | 650 | s5l_lcd_write_cmd(R_MEMORY_WRITE); |
650 | } | 651 | } |
651 | 652 | ||
652 | 653 | ||
653 | /* Copy display bitmap to hardware */ | 654 | /* Copy display bitmap to hardware */ |
654 | for (y = 0; y < LCD_HEIGHT; y++) { | 655 | for (y = 0; y < LCD_HEIGHT; y++) { |
655 | for (x = 0; x < LCD_WIDTH; x++) { | 656 | for (x = 0; x < LCD_WIDTH; x++) { |
656 | lcd_write_pixel(*(p++)); | 657 | lcd_write_pixel(*(p++)); |
657 | } | 658 | } |
658 | } | 659 | } |
659 | } | 660 | } |
660 | 661 | ||
661 | /* Update a fraction of the display. */ | 662 | /* Update a fraction of the display. */ |
662 | void lcd_update_rect(int, int, int, int) ICODE_ATTR; | 663 | void lcd_update_rect(int, int, int, int) ICODE_ATTR; |
663 | void lcd_update_rect(int x, int y, int width, int height) | 664 | void lcd_update_rect(int x, int y, int width, int height) |
664 | { | 665 | { |
665 | int xx,yy; | 666 | int xx,yy; |
666 | int y0, x0, y1, x1; | 667 | int y0, x0, y1, x1; |
667 | fb_data* p; | 668 | fb_data* p; |
668 | 669 | ||
669 | x0 = x; /* start horiz */ | 670 | x0 = x; /* start horiz */ |
670 | y0 = y; /* start vert */ | 671 | y0 = y; /* start vert */ |
671 | x1 = (x + width) - 1; /* max horiz */ | 672 | x1 = (x + width) - 1; /* max horiz */ |
672 | y1 = (y + height) - 1; /* max vert */ | 673 | y1 = (y + height) - 1; /* max vert */ |
673 | 674 | ||
674 | if (lcd_type==0) { | 675 | if (lcd_type==0) { |
675 | s5l_lcd_write_cmd_data(R_HORIZ_ADDR_START_POS, x0); | 676 | s5l_lcd_write_cmd_data(R_HORIZ_ADDR_START_POS, x0); |
676 | s5l_lcd_write_cmd_data(R_HORIZ_ADDR_END_POS, x1); | 677 | s5l_lcd_write_cmd_data(R_HORIZ_ADDR_END_POS, x1); |
677 | s5l_lcd_write_cmd_data(R_VERT_ADDR_START_POS, y0); | 678 | s5l_lcd_write_cmd_data(R_VERT_ADDR_START_POS, y0); |
678 | s5l_lcd_write_cmd_data(R_VERT_ADDR_END_POS, y1); | 679 | s5l_lcd_write_cmd_data(R_VERT_ADDR_END_POS, y1); |
679 | 680 | ||
680 | s5l_lcd_write_cmd_data(R_HORIZ_GRAM_ADDR_SET, (x1 << 8) | x0); | 681 | s5l_lcd_write_cmd_data(R_HORIZ_GRAM_ADDR_SET, (x1 << 8) | x0); |
681 | s5l_lcd_write_cmd_data(R_VERT_GRAM_ADDR_SET, (y1 << 8) | y0); | 682 | s5l_lcd_write_cmd_data(R_VERT_GRAM_ADDR_SET, (y1 << 8) | y0); |
682 | 683 | ||
683 | s5l_lcd_write_cmd(0); | 684 | s5l_lcd_write_cmd(0); |
684 | s5l_lcd_write_cmd(R_WRITE_DATA_TO_GRAM); | 685 | s5l_lcd_write_cmd(R_WRITE_DATA_TO_GRAM); |
685 | } else { | 686 | } else { |
686 | s5l_lcd_write_cmd(R_COLUMN_ADDR_SET); | 687 | s5l_lcd_write_cmd(R_COLUMN_ADDR_SET); |
687 | s5l_lcd_write_wdata(x0); /* Start column */ | 688 | s5l_lcd_write_wdata(x0); /* Start column */ |
688 | s5l_lcd_write_wdata(x1); /* End column */ | 689 | s5l_lcd_write_wdata(x1); /* End column */ |
689 | 690 | ||
690 | s5l_lcd_write_cmd(R_ROW_ADDR_SET); | 691 | s5l_lcd_write_cmd(R_ROW_ADDR_SET); |
691 | s5l_lcd_write_wdata(y0); /* Start row */ | 692 | s5l_lcd_write_wdata(y0); /* Start row */ |
692 | s5l_lcd_write_wdata(y1); /* End row */ | 693 | s5l_lcd_write_wdata(y1); /* End row */ |
693 | 694 | ||
694 | s5l_lcd_write_cmd(R_MEMORY_WRITE); | 695 | s5l_lcd_write_cmd(R_MEMORY_WRITE); |
695 | } | 696 | } |
696 | 697 | ||
697 | 698 | ||
698 | /* Copy display bitmap to hardware */ | 699 | /* Copy display bitmap to hardware */ |
699 | p = &lcd_framebuffer[y0][x0]; | 700 | p = &lcd_framebuffer[y0][x0]; |
700 | yy = height; | 701 | yy = height; |
701 | for (yy = y0; yy <= y1; yy++) { | 702 | for (yy = y0; yy <= y1; yy++) { |
702 | for (xx = x0; xx <= x1; xx++) { | 703 | for (xx = x0; xx <= x1; xx++) { |
703 | lcd_write_pixel(*(p++)); | 704 | lcd_write_pixel(*(p++)); |
704 | } | 705 | } |
705 | p += LCD_WIDTH - width; | 706 | p += LCD_WIDTH - width; |
706 | } | 707 | } |
707 | } | 708 | } |
708 | 709 | ||
709 | /*** update functions ***/ | 710 | /*** update functions ***/ |
710 | 711 | ||
711 | #define CSUB_X 2 | 712 | #define CSUB_X 2 |
712 | #define CSUB_Y 2 | 713 | #define CSUB_Y 2 |
713 | 714 | ||
714 | /* YUV- > RGB565 conversion | 715 | /* YUV- > RGB565 conversion |
715 | * |R| |1.000000 -0.000001 1.402000| |Y'| | 716 | * |R| |1.000000 -0.000001 1.402000| |Y'| |
716 | * |G| = |1.000000 -0.334136 -0.714136| |Pb| | 717 | * |G| = |1.000000 -0.334136 -0.714136| |Pb| |
717 | * |B| |1.000000 1.772000 0.000000| |Pr| | 718 | * |B| |1.000000 1.772000 0.000000| |Pr| |
718 | * Scaled, normalized, rounded and tweaked to yield RGB 565: | 719 | * Scaled, normalized, rounded and tweaked to yield RGB 565: |
719 | * |R| |74 0 101| |Y' - 16| >> 9 | 720 | * |R| |74 0 101| |Y' - 16| >> 9 |
720 | * |G| = |74 -24 -51| |Cb - 128| >> 8 | 721 | * |G| = |74 -24 -51| |Cb - 128| >> 8 |
721 | * |B| |74 128 0| |Cr - 128| >> 9 | 722 | * |B| |74 128 0| |Cr - 128| >> 9 |
722 | */ | 723 | */ |
723 | 724 | ||
724 | #define RGBYFAC 74 /* 1.0 */ | 725 | #define RGBYFAC 74 /* 1.0 */ |
725 | #define RVFAC 101 /* 1.402 */ | 726 | #define RVFAC 101 /* 1.402 */ |
726 | #define GVFAC (-51) /* -0.714136 */ | 727 | #define GVFAC (-51) /* -0.714136 */ |
727 | #define GUFAC (-24) /* -0.334136 */ | 728 | #define GUFAC (-24) /* -0.334136 */ |
728 | #define BUFAC 128 /* 1.772 */ | 729 | #define BUFAC 128 /* 1.772 */ |
729 | 730 | ||
730 | /* ROUNDOFFS contain constant for correct round-offs as well as | 731 | /* ROUNDOFFS contain constant for correct round-offs as well as |
731 | constant parts of the conversion matrix (e.g. (Y'-16)*RGBYFAC | 732 | constant parts of the conversion matrix (e.g. (Y'-16)*RGBYFAC |
732 | -> constant part = -16*RGBYFAC). Through extraction of these | 733 | -> constant part = -16*RGBYFAC). Through extraction of these |
733 | constant parts we save at leat 4 substractions in the conversion | 734 | constant parts we save at leat 4 substractions in the conversion |
734 | loop */ | 735 | loop */ |
735 | #define ROUNDOFFSR (256 - 16*RGBYFAC - 128*RVFAC) | 736 | #define ROUNDOFFSR (256 - 16*RGBYFAC - 128*RVFAC) |
736 | #define ROUNDOFFSG (128 - 16*RGBYFAC - 128*GVFAC - 128*GUFAC) | 737 | #define ROUNDOFFSG (128 - 16*RGBYFAC - 128*GVFAC - 128*GUFAC) |
737 | #define ROUNDOFFSB (256 - 16*RGBYFAC - 128*BUFAC) | 738 | #define ROUNDOFFSB (256 - 16*RGBYFAC - 128*BUFAC) |
738 | 739 | ||
739 | #define MAX_5BIT 0x1f | 740 | #define MAX_5BIT 0x1f |
740 | #define MAX_6BIT 0x3f | 741 | #define MAX_6BIT 0x3f |
741 | 742 | ||
742 | /* Performance function to blit a YUV bitmap directly to the LCD */ | 743 | /* Performance function to blit a YUV bitmap directly to the LCD */ |
743 | void lcd_blit_yuv(unsigned char * const src[3], | 744 | void lcd_blit_yuv(unsigned char * const src[3], |
744 | int src_x, int src_y, int stride, | 745 | int src_x, int src_y, int stride, |
745 | int x, int y, int width, int height) | 746 | int x, int y, int width, int height) |
746 | { | 747 | { |
747 | int h; | 748 | int h; |
748 | int y0, x0, y1, x1; | 749 | int y0, x0, y1, x1; |
749 | 750 | ||
750 | width = (width + 1) & ~1; | 751 | width = (width + 1) & ~1; |
751 | 752 | ||
752 | x0 = x; /* start horiz */ | 753 | x0 = x; /* start horiz */ |
753 | y0 = y; /* start vert */ | 754 | y0 = y; /* start vert */ |
754 | x1 = (x + width) - 1; /* max horiz */ | 755 | x1 = (x + width) - 1; /* max horiz */ |
755 | y1 = (y + height) - 1; /* max vert */ | 756 | y1 = (y + height) - 1; /* max vert */ |
756 | 757 | ||
757 | if (lcd_type==0) { | 758 | if (lcd_type==0) { |
758 | s5l_lcd_write_cmd_data(R_HORIZ_ADDR_START_POS, x0); | 759 | s5l_lcd_write_cmd_data(R_HORIZ_ADDR_START_POS, x0); |
759 | s5l_lcd_write_cmd_data(R_HORIZ_ADDR_END_POS, x1); | 760 | s5l_lcd_write_cmd_data(R_HORIZ_ADDR_END_POS, x1); |
760 | s5l_lcd_write_cmd_data(R_VERT_ADDR_START_POS, y0); | 761 | s5l_lcd_write_cmd_data(R_VERT_ADDR_START_POS, y0); |
761 | s5l_lcd_write_cmd_data(R_VERT_ADDR_END_POS, y1); | 762 | s5l_lcd_write_cmd_data(R_VERT_ADDR_END_POS, y1); |
762 | 763 | ||
763 | s5l_lcd_write_cmd_data(R_HORIZ_GRAM_ADDR_SET, (x1 << 8) | x0); | 764 | s5l_lcd_write_cmd_data(R_HORIZ_GRAM_ADDR_SET, (x1 << 8) | x0); |
764 | s5l_lcd_write_cmd_data(R_VERT_GRAM_ADDR_SET, (y1 << 8) | y0); | 765 | s5l_lcd_write_cmd_data(R_VERT_GRAM_ADDR_SET, (y1 << 8) | y0); |
765 | 766 | ||
766 | s5l_lcd_write_cmd(0); | 767 | s5l_lcd_write_cmd(0); |
767 | s5l_lcd_write_cmd(R_WRITE_DATA_TO_GRAM); | 768 | s5l_lcd_write_cmd(R_WRITE_DATA_TO_GRAM); |
768 | } else { | 769 | } else { |
769 | s5l_lcd_write_cmd(R_COLUMN_ADDR_SET); | 770 | s5l_lcd_write_cmd(R_COLUMN_ADDR_SET); |
770 | s5l_lcd_write_wdata(x0); /* Start column */ | 771 | s5l_lcd_write_wdata(x0); /* Start column */ |
771 | s5l_lcd_write_wdata(x1); /* End column */ | 772 | s5l_lcd_write_wdata(x1); /* End column */ |
772 | 773 | ||
773 | s5l_lcd_write_cmd(R_ROW_ADDR_SET); | 774 | s5l_lcd_write_cmd(R_ROW_ADDR_SET); |
774 | s5l_lcd_write_wdata(y0); /* Start row */ | 775 | s5l_lcd_write_wdata(y0); /* Start row */ |
775 | s5l_lcd_write_wdata(y1); /* End row */ | 776 | s5l_lcd_write_wdata(y1); /* End row */ |
776 | 777 | ||
777 | s5l_lcd_write_cmd(R_MEMORY_WRITE); | 778 | s5l_lcd_write_cmd(R_MEMORY_WRITE); |
778 | } | 779 | } |
779 | 780 | ||
780 | const int stride_div_csub_x = stride/CSUB_X; | 781 | const int stride_div_csub_x = stride/CSUB_X; |
781 | 782 | ||
782 | h = height; | 783 | h = height; |
783 | while (h > 0) { | 784 | while (h > 0) { |
784 | /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */ | 785 | /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */ |
785 | const unsigned char *ysrc = src[0] + stride * src_y + src_x; | 786 | const unsigned char *ysrc = src[0] + stride * src_y + src_x; |
786 | 787 | ||
787 | const int uvoffset = stride_div_csub_x * (src_y/CSUB_Y) + | 788 | const int uvoffset = stride_div_csub_x * (src_y/CSUB_Y) + |
788 | (src_x/CSUB_X); | 789 | (src_x/CSUB_X); |
789 | 790 | ||
790 | const unsigned char *usrc = src[1] + uvoffset; | 791 | const unsigned char *usrc = src[1] + uvoffset; |
791 | const unsigned char *vsrc = src[2] + uvoffset; | 792 | const unsigned char *vsrc = src[2] + uvoffset; |
792 | const unsigned char *row_end = ysrc + width; | 793 | const unsigned char *row_end = ysrc + width; |
793 | 794 | ||
794 | int yp, up, vp; | 795 | int yp, up, vp; |
795 | int red1, green1, blue1; | 796 | int red1, green1, blue1; |
796 | int red2, green2, blue2; | 797 | int red2, green2, blue2; |
797 | 798 | ||
798 | int rc, gc, bc; | 799 | int rc, gc, bc; |
799 | 800 | ||
800 | do | 801 | do |
801 | { | 802 | { |
802 | up = *usrc++; | 803 | up = *usrc++; |
803 | vp = *vsrc++; | 804 | vp = *vsrc++; |
804 | rc = RVFAC * vp + ROUNDOFFSR; | 805 | rc = RVFAC * vp + ROUNDOFFSR; |
805 | gc = GVFAC * vp + GUFAC * up + ROUNDOFFSG; | 806 | gc = GVFAC * vp + GUFAC * up + ROUNDOFFSG; |
806 | bc = BUFAC * up + ROUNDOFFSB; | 807 | bc = BUFAC * up + ROUNDOFFSB; |
807 | 808 | ||
808 | /* Pixel 1 -> RGB565 */ | 809 | /* Pixel 1 -> RGB565 */ |
809 | yp = *ysrc++ * RGBYFAC; | 810 | yp = *ysrc++ * RGBYFAC; |
810 | red1 = (yp + rc) >> 9; | 811 | red1 = (yp + rc) >> 9; |
811 | green1 = (yp + gc) >> 8; | 812 | green1 = (yp + gc) >> 8; |
812 | blue1 = (yp + bc) >> 9; | 813 | blue1 = (yp + bc) >> 9; |
813 | 814 | ||
814 | /* Pixel 2 -> RGB565 */ | 815 | /* Pixel 2 -> RGB565 */ |
815 | yp = *ysrc++ * RGBYFAC; | 816 | yp = *ysrc++ * RGBYFAC; |
816 | red2 = (yp + rc) >> 9; | 817 | red2 = (yp + rc) >> 9; |
817 | green2 = (yp + gc) >> 8; | 818 | green2 = (yp + gc) >> 8; |
818 | blue2 = (yp + bc) >> 9; | 819 | blue2 = (yp + bc) >> 9; |
819 | 820 | ||
820 | /* Since out of bounds errors are relatively rare, we check two | 821 | /* Since out of bounds errors are relatively rare, we check two |
821 | pixels at once to see if any components are out of bounds, and | 822 | pixels at once to see if any components are out of bounds, and |
822 | then fix whichever is broken. This works due to high values and | 823 | then fix whichever is broken. This works due to high values and |
823 | negative values both being !=0 when bitmasking them. | 824 | negative values both being !=0 when bitmasking them. |
824 | We first check for red and blue components (5bit range). */ | 825 | We first check for red and blue components (5bit range). */ |
825 | if ((red1 | blue1 | red2 | blue2) & ~MAX_5BIT) | 826 | if ((red1 | blue1 | red2 | blue2) & ~MAX_5BIT) |
826 | { | 827 | { |
827 | if (red1 & ~MAX_5BIT) | 828 | if (red1 & ~MAX_5BIT) |
828 | red1 = (red1 >> 31) ? 0 : MAX_5BIT; | 829 | red1 = (red1 >> 31) ? 0 : MAX_5BIT; |
829 | if (blue1 & ~MAX_5BIT) | 830 | if (blue1 & ~MAX_5BIT) |
830 | blue1 = (blue1 >> 31) ? 0 : MAX_5BIT; | 831 | blue1 = (blue1 >> 31) ? 0 : MAX_5BIT; |
831 | if (red2 & ~MAX_5BIT) | 832 | if (red2 & ~MAX_5BIT) |
832 | red2 = (red2 >> 31) ? 0 : MAX_5BIT; | 833 | red2 = (red2 >> 31) ? 0 : MAX_5BIT; |
833 | if (blue2 & ~MAX_5BIT) | 834 | if (blue2 & ~MAX_5BIT) |
834 | blue2 = (blue2 >> 31) ? 0 : MAX_5BIT; | 835 | blue2 = (blue2 >> 31) ? 0 : MAX_5BIT; |
835 | } | 836 | } |
836 | /* We second check for green component (6bit range) */ | 837 | /* We second check for green component (6bit range) */ |
837 | if ((green1 | green2) & ~MAX_6BIT) | 838 | if ((green1 | green2) & ~MAX_6BIT) |
838 | { | 839 | { |
839 | if (green1 & ~MAX_6BIT) | 840 | if (green1 & ~MAX_6BIT) |
840 | green1 = (green1 >> 31) ? 0 : MAX_6BIT; | 841 | green1 = (green1 >> 31) ? 0 : MAX_6BIT; |
841 | if (green2 & ~MAX_6BIT) | 842 | if (green2 & ~MAX_6BIT) |
842 | green2 = (green2 >> 31) ? 0 : MAX_6BIT; | 843 | green2 = (green2 >> 31) ? 0 : MAX_6BIT; |
843 | } | 844 | } |
844 | 845 | ||
845 | /* output 2 pixels */ | 846 | /* output 2 pixels */ |
846 | lcd_write_pixel((red1 << 11) | (green1 << 5) | blue1); | 847 | lcd_write_pixel((red1 << 11) | (green1 << 5) | blue1); |
847 | lcd_write_pixel((red2 << 11) | (green2 << 5) | blue2); | 848 | lcd_write_pixel((red2 << 11) | (green2 << 5) | blue2); |
848 | } | 849 | } |
849 | while (ysrc < row_end); | 850 | while (ysrc < row_end); |
850 | 851 | ||
851 | src_y++; | 852 | src_y++; |
852 | h--; | 853 | h--; |
853 | } | 854 | } |
854 | } | 855 | } |