summaryrefslogtreecommitdiff
path: root/firmware/target/arm/ipod/lcd-gray.c
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2008-01-12 00:59:18 +0000
committerJens Arnold <amiconn@rockbox.org>2008-01-12 00:59:18 +0000
commit41cd44caa7b4799dcc14eda33f0f5cf93152a6e0 (patch)
treefcaa7a94441ace95ba74faa9f01397a7d720a7d7 /firmware/target/arm/ipod/lcd-gray.c
parent9f686700d47e8fcfa0fec65bfbfcf5d5cde3f752 (diff)
downloadrockbox-41cd44caa7b4799dcc14eda33f0f5cf93152a6e0.tar.gz
rockbox-41cd44caa7b4799dcc14eda33f0f5cf93152a6e0.zip
Greyscale ipod lcd driver: * Assembler optimised low level functions. PP5002 targets benefit most (lcd_update() speedup >50%, and the greyscale overlay no longer makes mp3 playback skip). * Consistent brace placement style.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16060 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm/ipod/lcd-gray.c')
-rw-r--r--firmware/target/arm/ipod/lcd-gray.c176
1 files changed, 43 insertions, 133 deletions
diff --git a/firmware/target/arm/ipod/lcd-gray.c b/firmware/target/arm/ipod/lcd-gray.c
index 5734480bee..b77d3eb7f6 100644
--- a/firmware/target/arm/ipod/lcd-gray.c
+++ b/firmware/target/arm/ipod/lcd-gray.c
@@ -74,56 +74,47 @@ static unsigned short contrast_reg_h;
74static int addr_offset; 74static int addr_offset;
75#if defined(IPOD_MINI) || defined(IPOD_MINI2G) 75#if defined(IPOD_MINI) || defined(IPOD_MINI2G)
76static int pix_offset; 76static int pix_offset;
77void lcd_write_data_shifted(const fb_data* p_bytes, int count);
77#endif 78#endif
78 79
79static const unsigned char dibits[16] ICONST_ATTR = {
80 0x00, 0x03, 0x0C, 0x0F, 0x30, 0x33, 0x3C, 0x3F,
81 0xC0, 0xC3, 0xCC, 0xCF, 0xF0, 0xF3, 0xFC, 0xFF
82};
83
84/* wait for LCD with timeout */ 80/* wait for LCD with timeout */
85static inline void lcd_wait_write(void) 81static inline void lcd_wait_write(void)
86{ 82{
87 while (LCD1_CONTROL & LCD1_BUSY_MASK); 83 while (LCD1_CONTROL & LCD1_BUSY_MASK);
88} 84}
89 85
90/* send LCD data */ 86/* send LCD command */
91#if CONFIG_CPU == PP5002 87static void lcd_prepare_cmd(unsigned cmd)
92STATICIRAM void ICODE_ATTR lcd_send_data(unsigned data)
93#else
94static void lcd_send_data(unsigned data)
95#endif
96{ 88{
97 lcd_wait_write(); 89 lcd_wait_write();
98#ifdef IPOD_MINI2G 90#ifdef IPOD_MINI2G
99 LCD1_CMD = data | 0x760000; 91 LCD1_CMD = cmd | 0x740000;
100#else 92#else
101 LCD1_DATA = data >> 8; 93 LCD1_CMD = 0;
102 lcd_wait_write(); 94 lcd_wait_write();
103 LCD1_DATA = data & 0xff; 95 LCD1_CMD = cmd;
104#endif 96#endif
105} 97}
106 98
107/* send LCD command */ 99/* send LCD command and data */
108static void lcd_prepare_cmd(unsigned cmd) 100static void lcd_cmd_and_data(unsigned cmd, unsigned data)
109{ 101{
110 lcd_wait_write(); 102 lcd_wait_write();
111#ifdef IPOD_MINI2G 103#ifdef IPOD_MINI2G
112 LCD1_CMD = cmd | 0x740000; 104 LCD1_CMD = cmd | 0x740000;
105 lcd_wait_write();
106 LCD1_CMD = data | 0x760000;
113#else 107#else
114 LCD1_CMD = 0; 108 LCD1_CMD = 0;
115 lcd_wait_write(); 109 lcd_wait_write();
116 LCD1_CMD = cmd; 110 LCD1_CMD = cmd;
111 lcd_wait_write();
112 LCD1_DATA = data >> 8;
113 lcd_wait_write();
114 LCD1_DATA = data & 0xff;
117#endif 115#endif
118} 116}
119 117
120/* send LCD command and data */
121static void lcd_cmd_and_data(unsigned cmd, unsigned data)
122{
123 lcd_prepare_cmd(cmd);
124 lcd_send_data(data);
125}
126
127/* LCD init */ 118/* LCD init */
128void lcd_init_device(void) 119void lcd_init_device(void)
129{ 120{
@@ -230,27 +221,29 @@ void lcd_set_invert_display(bool yesno)
230void lcd_set_flip(bool yesno) 221void lcd_set_flip(bool yesno)
231{ 222{
232#if defined(IPOD_MINI) || defined(IPOD_MINI2G) 223#if defined(IPOD_MINI) || defined(IPOD_MINI2G)
233 if (yesno) { 224 if (yesno)
234 /* 168x112, inverse COM order */ 225 { /* 168x112, inverse COM order */
235 lcd_cmd_and_data(R_DRV_OUTPUT_CONTROL, 0x020d); 226 lcd_cmd_and_data(R_DRV_OUTPUT_CONTROL, 0x020d);
236 lcd_cmd_and_data(R_1ST_SCR_DRV_POS, 0x8316); /* 22..131 */ 227 lcd_cmd_and_data(R_1ST_SCR_DRV_POS, 0x8316); /* 22..131 */
237 addr_offset = (22 << 5) | (20 - 4); 228 addr_offset = (22 << 5) | (20 - 4);
238 pix_offset = -2; 229 pix_offset = -2;
239 } else { 230 }
240 /* 168x112, inverse SEG order */ 231 else
232 { /* 168x112, inverse SEG order */
241 lcd_cmd_and_data(R_DRV_OUTPUT_CONTROL, 0x010d); 233 lcd_cmd_and_data(R_DRV_OUTPUT_CONTROL, 0x010d);
242 lcd_cmd_and_data(R_1ST_SCR_DRV_POS, 0x6d00); /* 0..109 */ 234 lcd_cmd_and_data(R_1ST_SCR_DRV_POS, 0x6d00); /* 0..109 */
243 addr_offset = 20; 235 addr_offset = 20;
244 pix_offset = 0; 236 pix_offset = 0;
245 } 237 }
246#else 238#else
247 if (yesno) { 239 if (yesno)
248 /* 168x128, inverse SEG & COM order */ 240 { /* 168x128, inverse SEG & COM order */
249 lcd_cmd_and_data(R_DRV_OUTPUT_CONTROL, 0x030f); 241 lcd_cmd_and_data(R_DRV_OUTPUT_CONTROL, 0x030f);
250 lcd_cmd_and_data(R_1ST_SCR_DRV_POS, 0x8304); /* 4..131 */ 242 lcd_cmd_and_data(R_1ST_SCR_DRV_POS, 0x8304); /* 4..131 */
251 addr_offset = (4 << 5) | (20 - 1); 243 addr_offset = (4 << 5) | (20 - 1);
252 } else { 244 }
253 /* 168x128 */ 245 else
246 { /* 168x128 */
254 lcd_cmd_and_data(R_DRV_OUTPUT_CONTROL, 0x000f); 247 lcd_cmd_and_data(R_DRV_OUTPUT_CONTROL, 0x000f);
255 lcd_cmd_and_data(R_1ST_SCR_DRV_POS, 0x7f00); /* 0..127 */ 248 lcd_cmd_and_data(R_1ST_SCR_DRV_POS, 0x7f00); /* 0..127 */
256 addr_offset = 20; 249 addr_offset = 20;
@@ -279,108 +272,38 @@ void lcd_enable(bool on)
279 272
280/*** update functions ***/ 273/*** update functions ***/
281 274
275/* Helper function. */
276void lcd_mono_data(const unsigned char *data, int count);
277
282/* Performance function that works with an external buffer 278/* Performance function that works with an external buffer
283 note that x, bwidtht and stride are in 8-pixel units! */ 279 note that x, bwidtht and stride are in 8-pixel units! */
284void lcd_blit(const unsigned char* data, int bx, int y, int bwidth, 280void lcd_blit(const unsigned char* data, int bx, int y, int bwidth,
285 int height, int stride) 281 int height, int stride)
286{ 282{
287 const unsigned char *src, *src_end; 283 while (height--)
288 284 {
289 while (height--) {
290 src = data;
291 src_end = data + bwidth;
292 lcd_cmd_and_data(R_RAM_ADDR_SET, (y++ << 5) + addr_offset - bx); 285 lcd_cmd_and_data(R_RAM_ADDR_SET, (y++ << 5) + addr_offset - bx);
293 lcd_prepare_cmd(R_RAM_DATA); 286 lcd_prepare_cmd(R_RAM_DATA);
294 do { 287
295 unsigned byte = *src++; 288 lcd_mono_data(data, bwidth);
296 lcd_send_data((dibits[byte>>4] << 8) | dibits[byte&0x0f]);
297 } while (src < src_end);
298 data += stride; 289 data += stride;
299 } 290 }
300} 291}
301 292
293/* Helper function for lcd_grey_phase_blit(). */
294void lcd_grey_data(unsigned char *values, unsigned char *phases, int count);
295
302/* Performance function that works with an external buffer 296/* Performance function that works with an external buffer
303 note that bx and bwidth are in 8-pixel units! */ 297 note that bx and bwidth are in 8-pixel units! */
304void lcd_grey_phase_blit(unsigned char *values, unsigned char *phases, 298void lcd_grey_phase_blit(unsigned char *values, unsigned char *phases,
305 int bx, int y, int bwidth, int height, int stride) 299 int bx, int y, int bwidth, int height, int stride)
306{ 300{
307 unsigned char *val, *ph; 301 while (height--)
308 int bw; 302 {
309
310 while (height--) {
311 lcd_cmd_and_data(R_RAM_ADDR_SET, (y++ << 5) + addr_offset - bx); 303 lcd_cmd_and_data(R_RAM_ADDR_SET, (y++ << 5) + addr_offset - bx);
312 lcd_prepare_cmd(R_RAM_DATA); 304 lcd_prepare_cmd(R_RAM_DATA);
313 305
314 val = values; 306 lcd_grey_data(values, phases, bwidth);
315 ph = phases;
316 bw = bwidth;
317 asm volatile (
318 "10: \n"
319 "ldmia %[ph], {r0-r1} \n" /* Fetch 8 pixel phases */
320 "ldmia %[val]!, {r2-r3} \n" /* Fetch 8 pixel values */
321#ifdef IPOD_MINI2G
322 "mov r4, #0x7600 \n"
323#else
324 "mov r4, #0 \n"
325#endif
326 "tst r0, #0x80 \n"
327 "orreq r4, r4, #0xc0 \n"
328 "tst r0, #0x8000 \n"
329 "orreq r4, r4, #0x30 \n"
330 "tst r0, #0x800000 \n"
331 "orreq r4, r4, #0x0c \n"
332 "tst r0, #0x80000000 \n"
333 "orreq r4, r4, #0x03 \n"
334 "bic r0, r0, %[clbt] \n"
335 "add r0, r0, r2 \n"
336
337#ifdef IPOD_MINI2G
338 "mov r4, r4, lsl #8 \n"
339#else
340 "1: \n"
341 "ldr r2, [%[lcdb]] \n"
342 "tst r2, #0x8000 \n"
343 "bne 1b \n"
344
345 "str r4, [%[lcdb], #0x10] \n"
346 "mov r4, #0 \n"
347#endif
348
349 "tst r1, #0x80 \n"
350 "orreq r4, r4, #0xc0 \n"
351 "tst r1, #0x8000 \n"
352 "orreq r4, r4, #0x30 \n"
353 "tst r1, #0x800000 \n"
354 "orreq r4, r4, #0x0c \n"
355 "tst r1, #0x80000000 \n"
356 "orreq r4, r4, #0x03 \n"
357 "bic r1, r1, %[clbt] \n"
358 "add r1, r1, r3 \n"
359
360 "stmia %[ph]!, {r0-r1} \n"
361
362 "1: \n"
363 "ldr r2, [%[lcdb]] \n"
364 "tst r2, #0x8000 \n"
365 "bne 1b \n"
366#ifdef IPOD_MINI2G
367 "str r4, [%[lcdb], #0x08] \n"
368#else
369 "str r4, [%[lcdb], #0x10] \n"
370#endif
371
372 "subs %[bw], %[bw], #1 \n"
373 "bne 10b \n"
374 : /* outputs */
375 [val]"+r"(val),
376 [ph] "+r"(ph),
377 [bw] "+r"(bw)
378 : /* inputs */
379 [clbt]"r"(0x80808080),
380 [lcdb]"r"(LCD1_BASE)
381 : /* clobbers */
382 "r0", "r1", "r2", "r3", "r4"
383 );
384 values += stride; 307 values += stride;
385 phases += stride; 308 phases += stride;
386 } 309 }
@@ -407,30 +330,17 @@ void lcd_update_rect(int x, int y, int width, int height)
407 x >>= 3; 330 x >>= 3;
408 width = xmax - x + 1; 331 width = xmax - x + 1;
409 332
410 for (; y <= ymax; y++) { 333 for (; y <= ymax; y++)
411 unsigned char *data, *data_end; 334 {
412
413 lcd_cmd_and_data(R_RAM_ADDR_SET, (y << 5) + addr_offset - x); 335 lcd_cmd_and_data(R_RAM_ADDR_SET, (y << 5) + addr_offset - x);
414 lcd_prepare_cmd(R_RAM_DATA); 336 lcd_prepare_cmd(R_RAM_DATA);
415 337
416 data = &lcd_framebuffer[y][2*x];
417 data_end = data + 2 * width;
418#if defined(IPOD_MINI) || defined(IPOD_MINI2G) 338#if defined(IPOD_MINI) || defined(IPOD_MINI2G)
419 if (pix_offset == -2) { 339 if (pix_offset == -2)
420 unsigned cur_word = *data++; 340 lcd_write_data_shifted(&lcd_framebuffer[y][2*x], width);
421 do { 341 else
422 cur_word = (cur_word << 8) | *data++;
423 cur_word = (cur_word << 8) | *data++;
424 lcd_send_data((cur_word >> 4) & 0xffff);
425 } while (data <= data_end);
426 } else
427#endif 342#endif
428 { 343 lcd_write_data(&lcd_framebuffer[y][2*x], width);
429 do {
430 unsigned highbyte = *data++;
431 lcd_send_data((highbyte << 8) | *data++);
432 } while (data < data_end);
433 }
434 } 344 }
435} 345}
436 346