diff options
author | Cástor Muñoz <cmvidal@gmail.com> | 2015-09-26 06:06:42 +0200 |
---|---|---|
committer | Cástor Muñoz <cmvidal@gmail.com> | 2015-12-17 09:14:58 +0100 |
commit | 5c67ebbc333b1a6394404ae6d312f93ca7db9899 (patch) | |
tree | 7f58dccec04edb174209e34d2fb53929e3f110df | |
parent | f753b8ead1a798b90b6c2ecd0c62c2f4b6c4eea7 (diff) | |
download | rockbox-5c67ebbc333b1a6394404ae6d312f93ca7db9899.tar.gz rockbox-5c67ebbc333b1a6394404ae6d312f93ca7db9899.zip |
iPod Classic: prepare LCD driver for the bootloader
Optimizes encoding of LCD command sequences.
Change-Id: I9d1eb735e5a972c1a176177ed570a3fe991d7b9f
-rw-r--r-- | firmware/export/s5l8702.h | 1 | ||||
-rw-r--r-- | firmware/target/arm/s5l8702/ipod6g/lcd-ipod6g.c | 268 |
2 files changed, 130 insertions, 139 deletions
diff --git a/firmware/export/s5l8702.h b/firmware/export/s5l8702.h index 6ec59eaf37..83d754d537 100644 --- a/firmware/export/s5l8702.h +++ b/firmware/export/s5l8702.h | |||
@@ -433,6 +433,7 @@ | |||
433 | #define LCD_CONFIG (*((uint32_t volatile*)(0x38300000))) | 433 | #define LCD_CONFIG (*((uint32_t volatile*)(0x38300000))) |
434 | #define LCD_WCMD (*((uint32_t volatile*)(0x38300004))) | 434 | #define LCD_WCMD (*((uint32_t volatile*)(0x38300004))) |
435 | #define LCD_STATUS (*((uint32_t volatile*)(0x3830001c))) | 435 | #define LCD_STATUS (*((uint32_t volatile*)(0x3830001c))) |
436 | #define LCD_PHTIME (*((uint32_t volatile*)(0x38300020))) | ||
436 | #define LCD_WDATA (*((uint32_t volatile*)(0x38300040))) | 437 | #define LCD_WDATA (*((uint32_t volatile*)(0x38300040))) |
437 | 438 | ||
438 | 439 | ||
diff --git a/firmware/target/arm/s5l8702/ipod6g/lcd-ipod6g.c b/firmware/target/arm/s5l8702/ipod6g/lcd-ipod6g.c index bf6c1a1402..45768f9bd4 100644 --- a/firmware/target/arm/s5l8702/ipod6g/lcd-ipod6g.c +++ b/firmware/target/arm/s5l8702/ipod6g/lcd-ipod6g.c | |||
@@ -54,147 +54,100 @@ static struct mutex lcd_mutex; | |||
54 | static uint16_t lcd_dblbuf[LCD_HEIGHT][LCD_WIDTH] CACHEALIGN_ATTR; | 54 | static uint16_t lcd_dblbuf[LCD_HEIGHT][LCD_WIDTH] CACHEALIGN_ATTR; |
55 | static bool lcd_ispowered; | 55 | static bool lcd_ispowered; |
56 | 56 | ||
57 | #define SLEEP 0 | 57 | #define CMD 0 /* send command with N data */ |
58 | #define CMD16 1 | 58 | #define MREG 1 /* write multiple registers */ |
59 | #define DATA16 2 | 59 | #define SLEEP 2 |
60 | #define REG15 3 | ||
61 | #define END 0xff | 60 | #define END 0xff |
62 | 61 | ||
62 | #define CMD16(len) (CMD | ((len) << 8)) | ||
63 | #define MREG16(len) (MREG | ((len) << 8)) | ||
64 | #define SLEEP16(t) (SLEEP | ((t) << 8)) | ||
65 | |||
63 | /* powersave sequences */ | 66 | /* powersave sequences */ |
64 | 67 | ||
65 | static const unsigned short lcd_sleep_sequence_01[] = | 68 | static const unsigned char lcd_sleep_seq_01[] = |
66 | { | 69 | { |
67 | CMD16, 0x028, /* Display Off */ | 70 | CMD, 0x28, 0, /* Display Off */ |
68 | SLEEP, 0x005, /* 50 ms */ | 71 | SLEEP, 5, /* 50 ms */ |
69 | CMD16, 0x010, /* Sleep In Mode */ | 72 | CMD, 0x10, 0, /* Sleep In Mode */ |
70 | SLEEP, 0x005, /* 50 ms */ | 73 | SLEEP, 5, /* 50 ms */ |
71 | END | 74 | END |
72 | }; | 75 | }; |
73 | 76 | ||
74 | static const unsigned short lcd_deep_stby_sequence_23[] = | 77 | static const unsigned short lcd_enter_deepstby_seq_23[] = |
75 | { | 78 | { |
76 | /* Display Off */ | 79 | /* Display Off */ |
77 | REG15, 0x007, 0x0172, | 80 | MREG16(1), 0x007, 0x0172, |
78 | REG15, 0x030, 0x03ff, | 81 | MREG16(1), 0x030, 0x03ff, |
79 | SLEEP, 0x00a, | 82 | SLEEP16(9), |
80 | REG15, 0x007, 0x0120, | 83 | MREG16(1), 0x007, 0x0120, |
81 | REG15, 0x030, 0x0000, | 84 | MREG16(1), 0x030, 0x0000, |
82 | REG15, 0x100, 0x0780, | 85 | MREG16(1), 0x100, 0x0780, |
83 | REG15, 0x007, 0x0000, | 86 | MREG16(1), 0x007, 0x0000, |
84 | REG15, 0x101, 0x0260, | 87 | MREG16(1), 0x101, 0x0260, |
85 | REG15, 0x102, 0x00a9, | 88 | MREG16(1), 0x102, 0x00a9, |
86 | SLEEP, 0x003, | 89 | SLEEP16(3), |
87 | REG15, 0x100, 0x0700, | 90 | MREG16(1), 0x100, 0x0700, |
88 | 91 | ||
89 | /* Deep Standby Mode */ | 92 | /* Deep Standby Mode */ |
90 | REG15, 0x100, 0x0704, | 93 | MREG16(1), 0x100, 0x0704, |
91 | SLEEP, 0x005, | 94 | SLEEP16(5), |
92 | END | 95 | END |
93 | }; | 96 | }; |
94 | 97 | ||
95 | #ifdef HAVE_LCD_SLEEP | 98 | #ifdef HAVE_LCD_SLEEP |
96 | /* init sequences */ | 99 | /* init sequences */ |
97 | 100 | ||
98 | static const unsigned short lcd_init_sequence_01[] = | 101 | static const unsigned char lcd_awake_seq_01[] = |
99 | { | 102 | { |
100 | CMD16, 0x011, /* Sleep Out Mode */ | 103 | CMD, 0x11, 0, /* Sleep Out Mode */ |
101 | SLEEP, 0x006, /* 60 ms */ | 104 | SLEEP, 6, /* 60 ms */ |
102 | CMD16, 0x029, /* Display On */ | 105 | CMD, 0x29, 0, /* Display On */ |
103 | END | 106 | END |
104 | }; | 107 | }; |
105 | 108 | ||
106 | static const unsigned short lcd_init_sequence_23[] = | 109 | static const unsigned short lcd_init_seq_23[] = |
107 | { | 110 | { |
108 | /* Display settings */ | 111 | /* Display settings */ |
109 | REG15, 0x008, 0x0808, | 112 | MREG16(1), 0x008, 0x0808, |
110 | REG15, 0x010, 0x0013, | 113 | MREG16(7), 0x010, 0x0013, 0x0300, 0x0101, 0x0a03, 0x0a0e, 0x0a19, 0x2402, |
111 | REG15, 0x011, 0x0300, | 114 | MREG16(1), 0x018, 0x0001, |
112 | REG15, 0x012, 0x0101, | 115 | MREG16(1), 0x090, 0x0021, |
113 | REG15, 0x013, 0x0a03, | ||
114 | REG15, 0x014, 0x0a0e, | ||
115 | REG15, 0x015, 0x0a19, | ||
116 | REG15, 0x016, 0x2402, | ||
117 | REG15, 0x018, 0x0001, | ||
118 | REG15, 0x090, 0x0021, | ||
119 | 116 | ||
120 | /* Gamma settings */ | 117 | /* Gamma settings */ |
121 | REG15, 0x300, 0x0307, | 118 | MREG16(14), 0x300, 0x0307, 0x0003, 0x0402, 0x0303, 0x0300, 0x0407, 0x1c04, |
122 | REG15, 0x301, 0x0003, | 119 | 0x0307, 0x0003, 0x0402, 0x0303, 0x0300, 0x0407, 0x1c04, |
123 | REG15, 0x302, 0x0402, | 120 | MREG16(14), 0x310, 0x0707, 0x0407, 0x0306, 0x0303, 0x0300, 0x0407, 0x1c01, |
124 | REG15, 0x303, 0x0303, | 121 | 0x0707, 0x0407, 0x0306, 0x0303, 0x0300, 0x0407, 0x1c01, |
125 | REG15, 0x304, 0x0300, | 122 | MREG16(14), 0x320, 0x0206, 0x0102, 0x0404, 0x0303, 0x0300, 0x0407, 0x1c1f, |
126 | REG15, 0x305, 0x0407, | 123 | 0x0206, 0x0102, 0x0404, 0x0303, 0x0300, 0x0407, 0x1c1f, |
127 | REG15, 0x306, 0x1c04, | ||
128 | REG15, 0x307, 0x0307, | ||
129 | REG15, 0x308, 0x0003, | ||
130 | REG15, 0x309, 0x0402, | ||
131 | REG15, 0x30a, 0x0303, | ||
132 | REG15, 0x30b, 0x0300, | ||
133 | REG15, 0x30c, 0x0407, | ||
134 | REG15, 0x30d, 0x1c04, | ||
135 | |||
136 | REG15, 0x310, 0x0707, | ||
137 | REG15, 0x311, 0x0407, | ||
138 | REG15, 0x312, 0x0306, | ||
139 | REG15, 0x313, 0x0303, | ||
140 | REG15, 0x314, 0x0300, | ||
141 | REG15, 0x315, 0x0407, | ||
142 | REG15, 0x316, 0x1c01, | ||
143 | REG15, 0x317, 0x0707, | ||
144 | REG15, 0x318, 0x0407, | ||
145 | REG15, 0x319, 0x0306, | ||
146 | REG15, 0x31a, 0x0303, | ||
147 | REG15, 0x31b, 0x0300, | ||
148 | REG15, 0x31c, 0x0407, | ||
149 | REG15, 0x31d, 0x1c01, | ||
150 | |||
151 | REG15, 0x320, 0x0206, | ||
152 | REG15, 0x321, 0x0102, | ||
153 | REG15, 0x322, 0x0404, | ||
154 | REG15, 0x323, 0x0303, | ||
155 | REG15, 0x324, 0x0300, | ||
156 | REG15, 0x325, 0x0407, | ||
157 | REG15, 0x326, 0x1c1f, | ||
158 | REG15, 0x327, 0x0206, | ||
159 | REG15, 0x328, 0x0102, | ||
160 | REG15, 0x329, 0x0404, | ||
161 | REG15, 0x32a, 0x0303, | ||
162 | REG15, 0x32b, 0x0300, | ||
163 | REG15, 0x32c, 0x0407, | ||
164 | REG15, 0x32d, 0x1c1f, | ||
165 | 124 | ||
166 | /* GRAM and Base Imagen settings (ili9326ds) */ | 125 | /* GRAM and Base Imagen settings (ili9326ds) */ |
167 | REG15, 0x400, 0x001d, | 126 | MREG16(2), 0x400, 0x001d, 0x0001, |
168 | REG15, 0x401, 0x0001, | 127 | MREG16(1), 0x205, 0x0060, |
169 | REG15, 0x205, 0x0060, | ||
170 | 128 | ||
171 | /* Power settings */ | 129 | /* Power settings */ |
172 | REG15, 0x007, 0x0001, | 130 | MREG16(1), 0x007, 0x0001, |
173 | REG15, 0x031, 0x0071, | 131 | MREG16(1), 0x031, 0x0071, |
174 | REG15, 0x110, 0x0001, | 132 | MREG16(1), 0x110, 0x0001, |
175 | REG15, 0x100, 0x17b0, | 133 | MREG16(6), 0x100, 0x17b0, 0x0220, 0x00bd, 0x1500, 0x0103, 0x0105, |
176 | REG15, 0x101, 0x0220, | ||
177 | REG15, 0x102, 0x00bd, | ||
178 | REG15, 0x103, 0x1500, | ||
179 | REG15, 0x105, 0x0103, | ||
180 | REG15, 0x106, 0x0105, | ||
181 | 134 | ||
182 | /* Display On */ | 135 | /* Display On */ |
183 | REG15, 0x007, 0x0021, | 136 | MREG16(1), 0x007, 0x0021, |
184 | REG15, 0x001, 0x0110, | 137 | MREG16(1), 0x001, 0x0110, |
185 | REG15, 0x003, 0x0230, | 138 | MREG16(1), 0x003, 0x0230, |
186 | REG15, 0x002, 0x0500, | 139 | MREG16(1), 0x002, 0x0500, |
187 | REG15, 0x007, 0x0031, | 140 | MREG16(1), 0x007, 0x0031, |
188 | REG15, 0x030, 0x0007, | 141 | MREG16(1), 0x030, 0x0007, |
189 | SLEEP, 0x003, | 142 | SLEEP16(3), |
190 | REG15, 0x030, 0x03ff, | 143 | MREG16(1), 0x030, 0x03ff, |
191 | SLEEP, 0x006, | 144 | SLEEP16(6), |
192 | REG15, 0x007, 0x0072, | 145 | MREG16(1), 0x007, 0x0072, |
193 | SLEEP, 0x00f, | 146 | SLEEP16(15), |
194 | REG15, 0x007, 0x0173, | 147 | MREG16(1), 0x007, 0x0173, |
195 | END | 148 | END |
196 | }; | 149 | }; |
197 | #endif | 150 | #endif /* HAVE_LCD_SLEEP */ |
198 | 151 | ||
199 | /* DMA configuration */ | 152 | /* DMA configuration */ |
200 | 153 | ||
@@ -261,30 +214,54 @@ static inline void s5l_lcd_write_data(unsigned short data) | |||
261 | LCD_WDATA = data; | 214 | LCD_WDATA = data; |
262 | } | 215 | } |
263 | 216 | ||
264 | static void lcd_run_sequence(const unsigned short *seq) | 217 | static void lcd_run_seq8(const unsigned char *seq) |
265 | { | 218 | { |
266 | unsigned short tmp; | 219 | int n; |
267 | 220 | ||
268 | while (1) switch (*seq++) | 221 | while (1) switch (*seq++) |
269 | { | 222 | { |
270 | case SLEEP: | 223 | case CMD: |
271 | sleep(*seq++); | ||
272 | break; | ||
273 | case CMD16: | ||
274 | s5l_lcd_write_cmd(*seq++); | 224 | s5l_lcd_write_cmd(*seq++); |
225 | n = *seq++; | ||
226 | while (n--) | ||
227 | s5l_lcd_write_data(*seq++); | ||
275 | break; | 228 | break; |
276 | case DATA16: | 229 | case SLEEP: |
277 | s5l_lcd_write_data(*seq++); | 230 | sleep(*seq++); |
278 | break; | ||
279 | case REG15: | ||
280 | tmp = *seq++; /* avoid compiler warning */ | ||
281 | s5l_lcd_write_reg(tmp, *seq++); | ||
282 | break; | 231 | break; |
283 | case END: | 232 | case END: |
284 | default: | 233 | default: |
285 | /* bye */ | 234 | /* bye */ |
286 | return; | 235 | return; |
287 | } | 236 | } |
237 | } | ||
238 | |||
239 | static void lcd_run_seq16(const unsigned short *seq) | ||
240 | { | ||
241 | int action, param; | ||
242 | unsigned short reg; | ||
243 | |||
244 | while (1) | ||
245 | { | ||
246 | action = *seq & 0xff; | ||
247 | param = *seq++ >> 8; | ||
248 | |||
249 | switch (action) | ||
250 | { | ||
251 | case MREG: | ||
252 | reg = *seq++; | ||
253 | while (param--) | ||
254 | s5l_lcd_write_reg(reg++, *seq++); | ||
255 | break; | ||
256 | case SLEEP: | ||
257 | sleep(param); | ||
258 | break; | ||
259 | case END: | ||
260 | default: | ||
261 | /* bye */ | ||
262 | return; | ||
263 | } | ||
264 | } | ||
288 | } | 265 | } |
289 | 266 | ||
290 | /*** hardware configuration ***/ | 267 | /*** hardware configuration ***/ |
@@ -314,36 +291,43 @@ bool lcd_active(void) | |||
314 | return lcd_ispowered; | 291 | return lcd_ispowered; |
315 | } | 292 | } |
316 | 293 | ||
317 | void lcd_shutdown(void) | 294 | void lcd_powersave(void) |
318 | { | ||
319 | pmu_write(0x2b, 0); /* Kill the backlight, instantly. */ | ||
320 | pmu_write(0x29, 0); | ||
321 | |||
322 | lcd_sleep(); | ||
323 | } | ||
324 | |||
325 | void lcd_sleep(void) | ||
326 | { | 295 | { |
327 | mutex_lock(&lcd_mutex); | 296 | mutex_lock(&lcd_mutex); |
328 | 297 | ||
329 | lcd_run_sequence((lcd_type & 2) ? lcd_deep_stby_sequence_23 | 298 | if (lcd_type & 2) |
330 | : lcd_sleep_sequence_01); | 299 | lcd_run_seq16(lcd_enter_deepstby_seq_23); |
300 | else | ||
301 | lcd_run_seq8(lcd_sleep_seq_01); | ||
331 | 302 | ||
332 | /* mask lcd controller clock gate */ | 303 | /* mask lcd controller clock gate */ |
333 | PWRCON(0) |= (1 << 1); | 304 | PWRCON(0) |= (1 << CLOCKGATE_LCD); |
334 | 305 | ||
335 | lcd_ispowered = false; | 306 | lcd_ispowered = false; |
336 | 307 | ||
337 | mutex_unlock(&lcd_mutex); | 308 | mutex_unlock(&lcd_mutex); |
338 | } | 309 | } |
339 | 310 | ||
311 | void lcd_shutdown(void) | ||
312 | { | ||
313 | pmu_write(0x2b, 0); /* Kill the backlight, instantly. */ | ||
314 | pmu_write(0x29, 0); | ||
315 | |||
316 | lcd_powersave(); | ||
317 | } | ||
318 | |||
340 | #ifdef HAVE_LCD_SLEEP | 319 | #ifdef HAVE_LCD_SLEEP |
320 | void lcd_sleep(void) | ||
321 | { | ||
322 | lcd_powersave(); | ||
323 | } | ||
324 | |||
341 | void lcd_awake(void) | 325 | void lcd_awake(void) |
342 | { | 326 | { |
343 | mutex_lock(&lcd_mutex); | 327 | mutex_lock(&lcd_mutex); |
344 | 328 | ||
345 | /* unmask lcd controller clock gate */ | 329 | /* unmask lcd controller clock gate */ |
346 | PWRCON(0) &= ~(1 << 1); | 330 | PWRCON(0) &= ~(1 << CLOCKGATE_LCD); |
347 | 331 | ||
348 | if (lcd_type & 2) { | 332 | if (lcd_type & 2) { |
349 | /* release from deep standby mode (ili9320ds s12.3) */ | 333 | /* release from deep standby mode (ili9320ds s12.3) */ |
@@ -352,10 +336,10 @@ void lcd_awake(void) | |||
352 | udelay(1000); | 336 | udelay(1000); |
353 | } | 337 | } |
354 | 338 | ||
355 | lcd_run_sequence(lcd_init_sequence_23); | 339 | lcd_run_seq16(lcd_init_seq_23); |
356 | } | 340 | } |
357 | else | 341 | else |
358 | lcd_run_sequence(lcd_init_sequence_01); | 342 | lcd_run_seq8(lcd_awake_seq_01); |
359 | 343 | ||
360 | lcd_ispowered = true; | 344 | lcd_ispowered = true; |
361 | 345 | ||
@@ -368,11 +352,17 @@ void lcd_awake(void) | |||
368 | /* LCD init */ | 352 | /* LCD init */ |
369 | void lcd_init_device(void) | 353 | void lcd_init_device(void) |
370 | { | 354 | { |
371 | /* Detect lcd type */ | ||
372 | mutex_init(&lcd_mutex); | 355 | mutex_init(&lcd_mutex); |
356 | |||
357 | /* unmask lcd controller clock gate */ | ||
358 | PWRCON(0) &= ~(1 << CLOCKGATE_LCD); | ||
359 | |||
360 | /* Detect lcd type */ | ||
373 | lcd_type = (PDAT6 & 0x30) >> 4; | 361 | lcd_type = (PDAT6 & 0x30) >> 4; |
362 | |||
374 | while (!(LCD_STATUS & 0x2)); | 363 | while (!(LCD_STATUS & 0x2)); |
375 | LCD_CONFIG = 0x80100db0; | 364 | LCD_CONFIG = 0x80100db0; |
365 | LCD_PHTIME = 0x33; | ||
376 | 366 | ||
377 | /* Configure DMA channel */ | 367 | /* Configure DMA channel */ |
378 | dmac_ch_init(&lcd_dma_ch, &lcd_dma_ch_cfg); | 368 | dmac_ch_init(&lcd_dma_ch, &lcd_dma_ch_cfg); |
@@ -398,7 +388,7 @@ void lcd_update(void) | |||
398 | } | 388 | } |
399 | 389 | ||
400 | /* Line write helper function. */ | 390 | /* Line write helper function. */ |
401 | extern void lcd_write_line(const fb_data *addr, | 391 | extern void lcd_write_line(const fb_data *addr, |
402 | int pixelcount, | 392 | int pixelcount, |
403 | const unsigned int lcd_base_addr); | 393 | const unsigned int lcd_base_addr); |
404 | 394 | ||
@@ -456,7 +446,7 @@ void lcd_update_rect(int x, int y, int width, int height) | |||
456 | int pixels = width * height; | 446 | int pixels = width * height; |
457 | fb_data* p = FBADDR(x,y); | 447 | fb_data* p = FBADDR(x,y); |
458 | uint16_t* out = lcd_dblbuf[0]; | 448 | uint16_t* out = lcd_dblbuf[0]; |
459 | 449 | ||
460 | #ifdef HAVE_LCD_SLEEP | 450 | #ifdef HAVE_LCD_SLEEP |
461 | if (!lcd_active()) return; | 451 | if (!lcd_active()) return; |
462 | #endif | 452 | #endif |
@@ -495,7 +485,7 @@ void lcd_blit_yuv(unsigned char * const src[3], | |||
495 | { | 485 | { |
496 | unsigned int z; | 486 | unsigned int z; |
497 | unsigned char const * yuv_src[3]; | 487 | unsigned char const * yuv_src[3]; |
498 | 488 | ||
499 | #ifdef HAVE_LCD_SLEEP | 489 | #ifdef HAVE_LCD_SLEEP |
500 | if (!lcd_active()) return; | 490 | if (!lcd_active()) return; |
501 | #endif | 491 | #endif |