summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sparmann <theseven@rockbox.org>2010-11-14 15:46:17 +0000
committerMichael Sparmann <theseven@rockbox.org>2010-11-14 15:46:17 +0000
commitcdbaa09fb73ce9ff04876c5f8464fc5f692b9e3f (patch)
treed376c0e8f65bccb13f6dbf12d93465b7ba4d7890
parent9321ce3febacfc6ef495a9d834edb3e74cf3ab5b (diff)
downloadrockbox-cdbaa09fb73ce9ff04876c5f8464fc5f692b9e3f.tar.gz
rockbox-cdbaa09fb73ce9ff04876c5f8464fc5f692b9e3f.zip
iPod Nano 2G LCD sleep: Send LCD_EVENT_ACTIVATION event
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28593 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/target/arm/s5l8700/ipodnano2g/lcd-nano2g.c1693
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
62int lcd_type; /* also needed in debug-s5l8700.c */ 62int lcd_type; /* also needed in debug-s5l8700.c */
63static int xoffset; /* needed for flip */ 63static int xoffset; /* needed for flip */
64static bool lcd_ispowered; 64static 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
74unsigned short lcd_init_sequence_0[] = { 74unsigned 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
207unsigned short lcd_init_sequence_1[] = { 207unsigned 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
325unsigned short lcd_init_sequence_2[] = { 325unsigned 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
396static inline void s5l_lcd_write_cmd_data(int cmd, int data) 396static 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
409static inline void s5l_lcd_write_cmd(unsigned short cmd) 409static 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
415static inline void s5l_lcd_write_wcmd(unsigned short cmd) 415static 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
423static inline void s5l_lcd_write_data(unsigned short data) 423static 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
429static inline void s5l_lcd_write_wdata(unsigned short data) 429static 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
439int lcd_default_contrast(void) 439int lcd_default_contrast(void)
440{ 440{
441 return 0x1f; 441 return 0x1f;
442} 442}
443 443
444void lcd_set_contrast(int val) 444void lcd_set_contrast(int val)
445{ 445{
446 (void)val; 446 (void)val;
447} 447}
448 448
449void lcd_set_invert_display(bool yesno) 449void 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) */
455void lcd_set_flip(bool yesno) 455void 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
470bool lcd_active(void) 470bool 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
477void lcd_wakeup(void) 477void 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}
547void lcd_awake(void) 547
548{ 548void lcd_awake(void)
549 if(!lcd_active()) lcd_wakeup(); 549{
550} 550 if(!lcd_active()) lcd_wakeup();
551#endif 551}
552 552#endif
553void lcd_shutdown(void) 553
554{ 554void 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
590void lcd_sleep(void) 591void lcd_sleep(void)
591{ 592{
592 lcd_shutdown(); 593 lcd_shutdown();
593} 594}
594 595
595/* LCD init */ 596/* LCD init */
596void lcd_init_device(void) 597void 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
613static inline void lcd_write_pixel(fb_data pixel) 614static 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. */
623void lcd_update(void) ICODE_ATTR; 624void lcd_update(void) ICODE_ATTR;
624void lcd_update(void) 625void 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. */
662void lcd_update_rect(int, int, int, int) ICODE_ATTR; 663void lcd_update_rect(int, int, int, int) ICODE_ATTR;
663void lcd_update_rect(int x, int y, int width, int height) 664void 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 */
743void lcd_blit_yuv(unsigned char * const src[3], 744void 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}