summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2008-01-09 23:48:26 +0000
committerJens Arnold <amiconn@rockbox.org>2008-01-09 23:48:26 +0000
commit6a56c14e17f6ba113ec0d4d40e75bffd61b293cc (patch)
tree64bcdd8d5d4afa2ca6dd1aa0976cdafa9a346b26
parent75380fd27d175bab1818ef35a9100e74fc6a461b (diff)
downloadrockbox-6a56c14e17f6ba113ec0d4d40e75bffd61b293cc.tar.gz
rockbox-6a56c14e17f6ba113ec0d4d40e75bffd61b293cc.zip
Greyscale library: Changed the internal data format once more (separated pixel values and phases), allowing for further optimisation of drawing, scrolling etc. * Optimised grey phase blitting in the core reduces CPU load on all architectures, most significantly on coldfire. Previous version was too slow to keep up at 45MHz, leading to unwanted graininess (update frequency was halved). Also fixed screendump on 2bpp targets with vertical pixel packing.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16043 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/plugin.h9
-rw-r--r--apps/plugins/lib/grey.h9
-rw-r--r--apps/plugins/lib/grey_core.c69
-rw-r--r--apps/plugins/lib/grey_draw.c17
-rw-r--r--apps/plugins/lib/grey_scroll.c16
-rw-r--r--firmware/export/lcd.h10
-rw-r--r--firmware/target/arm/ipod/lcd-gray.c134
-rw-r--r--firmware/target/coldfire/iaudio/m5/lcd-as-m5.S189
-rw-r--r--firmware/target/coldfire/iaudio/m5/lcd-m5.c12
-rw-r--r--firmware/target/coldfire/iriver/h100/lcd-as-h100.S189
-rw-r--r--firmware/target/coldfire/iriver/h100/lcd-h100.c12
-rw-r--r--firmware/target/sh/archos/lcd-archos-bitmap.c12
-rw-r--r--firmware/target/sh/archos/lcd-as-archos-bitmap.S125
13 files changed, 476 insertions, 327 deletions
diff --git a/apps/plugin.h b/apps/plugin.h
index 849c10bb89..a3ec9c3148 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -119,12 +119,12 @@
119#define PLUGIN_MAGIC 0x526F634B /* RocK */ 119#define PLUGIN_MAGIC 0x526F634B /* RocK */
120 120
121/* increase this every time the api struct changes */ 121/* increase this every time the api struct changes */
122#define PLUGIN_API_VERSION 95 122#define PLUGIN_API_VERSION 96
123 123
124/* update this to latest version if a change to the api struct breaks 124/* update this to latest version if a change to the api struct breaks
125 backwards compatibility (and please take the opportunity to sort in any 125 backwards compatibility (and please take the opportunity to sort in any
126 new function which are "waiting" at the end of the function table) */ 126 new function which are "waiting" at the end of the function table) */
127#define PLUGIN_MIN_API_VERSION 95 127#define PLUGIN_MIN_API_VERSION 96
128 128
129/* plugin return codes */ 129/* plugin return codes */
130enum plugin_status { 130enum plugin_status {
@@ -268,8 +268,9 @@ struct plugin_api {
268 int height); 268 int height);
269#endif 269#endif
270#if defined(HAVE_LCD_BITMAP) && (LCD_DEPTH < 4) && !defined(SIMULATOR) 270#if defined(HAVE_LCD_BITMAP) && (LCD_DEPTH < 4) && !defined(SIMULATOR)
271 void (*lcd_grey_phase_blit)(const struct grey_data *data, int bx, int by, 271 void (*lcd_grey_phase_blit)(unsigned char *values, unsigned char *phases,
272 int bwidth, int bheight, int stride); 272 int bx, int by, int bwidth, int bheight,
273 int stride);
273#endif 274#endif
274#if defined(HAVE_LCD_COLOR) 275#if defined(HAVE_LCD_COLOR)
275 void (*lcd_yuv_blit)(unsigned char * const src[3], 276 void (*lcd_yuv_blit)(unsigned char * const src[3],
diff --git a/apps/plugins/lib/grey.h b/apps/plugins/lib/grey.h
index 136794bd26..9a3bd7d3f8 100644
--- a/apps/plugins/lib/grey.h
+++ b/apps/plugins/lib/grey.h
@@ -121,12 +121,12 @@ void grey_ub_scroll_down(int count);
121#endif 121#endif
122 122
123#if LCD_PIXELFORMAT == HORIZONTAL_PACKING 123#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
124#define _GREY_X_ADVANCE sizeof(struct grey_data) 124#define _GREY_X_ADVANCE 1
125#else 125#else
126#if LCD_DEPTH == 1 126#if LCD_DEPTH == 1
127#define _GREY_X_ADVANCE (8*sizeof(struct grey_data)) 127#define _GREY_X_ADVANCE 8
128#elif LCD_DEPTH == 2 128#elif LCD_DEPTH == 2
129#define _GREY_X_ADVANCE (4*sizeof(struct grey_data)) 129#define _GREY_X_ADVANCE 4
130#endif 130#endif
131#endif /* LCD_PIXELFORMAT */ 131#endif /* LCD_PIXELFORMAT */
132 132
@@ -146,7 +146,8 @@ struct _grey_info
146#endif 146#endif
147 unsigned long flags; /* various flags, see #defines */ 147 unsigned long flags; /* various flags, see #defines */
148#ifndef SIMULATOR 148#ifndef SIMULATOR
149 struct grey_data *data; /* start of greyscale display data */ 149 unsigned char *values; /* start of greyscale pixel values */
150 unsigned char *phases; /* start of greyscale pixel phases */
150#endif 151#endif
151 unsigned char *buffer; /* start of chunky pixel buffer (for buffered mode) */ 152 unsigned char *buffer; /* start of chunky pixel buffer (for buffered mode) */
152 unsigned char gvalue[256]; /* calculated brightness -> greyvalue table */ 153 unsigned char gvalue[256]; /* calculated brightness -> greyvalue table */
diff --git a/apps/plugins/lib/grey_core.c b/apps/plugins/lib/grey_core.c
index b3ab640602..43eed9b022 100644
--- a/apps/plugins/lib/grey_core.c
+++ b/apps/plugins/lib/grey_core.c
@@ -222,11 +222,13 @@ static inline void _deferred_update(void)
222static void _timer_isr(void) 222static void _timer_isr(void)
223{ 223{
224#if LCD_PIXELFORMAT == HORIZONTAL_PACKING 224#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
225 _grey_rb->lcd_grey_phase_blit(_grey_info.data, _grey_info.bx, _grey_info.y, 225 _grey_rb->lcd_grey_phase_blit(_grey_info.values, _grey_info.phases,
226 _grey_info.bx, _grey_info.y,
226 _grey_info.bwidth, _grey_info.height, 227 _grey_info.bwidth, _grey_info.height,
227 _grey_info.width); 228 _grey_info.width);
228#else 229#else
229 _grey_rb->lcd_grey_phase_blit(_grey_info.data, _grey_info.x, _grey_info.by, 230 _grey_rb->lcd_grey_phase_blit(_grey_info.values, _grey_info.phases,
231 _grey_info.x, _grey_info.by,
230 _grey_info.width, _grey_info.bheight, 232 _grey_info.width, _grey_info.bheight,
231 _grey_info.width); 233 _grey_info.width);
232#endif 234#endif
@@ -321,7 +323,7 @@ bool grey_init(struct plugin_api* newrb, unsigned char *gbuf, long gbuf_size,
321 long plane_size, buftaken; 323 long plane_size, buftaken;
322 unsigned data; 324 unsigned data;
323#ifndef SIMULATOR 325#ifndef SIMULATOR
324 struct grey_data *grey_data, *grey_end; 326 unsigned *dst, *end;
325#endif 327#endif
326 328
327 _grey_rb = newrb; 329 _grey_rb = newrb;
@@ -343,35 +345,41 @@ bool grey_init(struct plugin_api* newrb, unsigned char *gbuf, long gbuf_size,
343#endif 345#endif
344#endif 346#endif
345 347
346 /* the buffer has to be long aligned */
347 buftaken = (-(long)gbuf) & 3;
348 gbuf += buftaken;
349
350 plane_size = _GREY_MULUQ(width, height); 348 plane_size = _GREY_MULUQ(width, height);
349#ifdef CPU_COLDFIRE
350 plane_size += (-plane_size) & 0xf; /* All buffers should be line aligned */
351 buftaken = (-(long)gbuf) & 0xf;
352#else
353 buftaken = (-(long)gbuf) & 3; /* All buffers must be long aligned. */
354#endif
355 gbuf += buftaken;
351 356
352 if (buffered) /* chunky buffer */ 357 if (buffered) /* chunky buffer */
353 { 358 {
354 buftaken += plane_size;
355 _grey_info.buffer = gbuf; 359 _grey_info.buffer = gbuf;
356 gbuf += plane_size; 360 gbuf += plane_size;
361 buftaken += plane_size;
357 } 362 }
358 buftaken += sizeof(struct grey_data) * plane_size;
359 if (buftaken > gbuf_size)
360 return false;
361
362#ifdef SIMULATOR 363#ifdef SIMULATOR
363 _grey_info.buffer = gbuf; 364 _grey_info.buffer = gbuf;
364#else 365#else
365 grey_data = (struct grey_data *)gbuf; 366 _grey_info.values = gbuf;
366 grey_end = grey_data + plane_size; 367 gbuf += plane_size;
367 _grey_info.data = grey_data; 368 _grey_info.phases = gbuf;
369#endif
370 buftaken += 2 * plane_size;
368 371
369 while (grey_data < grey_end) 372 if (buftaken > gbuf_size)
370 { 373 return false;
371 grey_data->phase = _grey_rb->rand() & 0xff; 374
372 grey_data->value = 128; /* init to white */ 375#ifndef SIMULATOR
373 grey_data++; 376 _grey_rb->memset(_grey_info.values, 0x80, plane_size);
374 } 377 dst = (unsigned*)(_grey_info.phases);
378 end = (unsigned*)(_grey_info.phases + plane_size);
379
380 do
381 *dst++ = _grey_rb->rand();
382 while (dst < end);
375#endif 383#endif
376 384
377 _grey_info.x = 0; 385 _grey_info.x = 0;
@@ -393,8 +401,7 @@ bool grey_init(struct plugin_api* newrb, unsigned char *gbuf, long gbuf_size,
393 _grey_info.drawmode = DRMODE_SOLID; 401 _grey_info.drawmode = DRMODE_SOLID;
394 _grey_info.curfont = FONT_SYSFIXED; 402 _grey_info.curfont = FONT_SYSFIXED;
395 403
396 404 /* precalculate the value -> pattern index conversion table, taking
397 /* precalculate the value -> pattern index conversion table, taking
398 linearisation and gamma correction into account */ 405 linearisation and gamma correction into account */
399 for (i = 0; i < 256; i++) 406 for (i = 0; i < 256; i++)
400 { 407 {
@@ -532,7 +539,7 @@ void grey_update_rect(int x, int y, int width, int height)
532 int idx = _GREY_MULUQ(_grey_info.width, y & ~3) + (x << 2) + (~y & 3); 539 int idx = _GREY_MULUQ(_grey_info.width, y & ~3) + (x << 2) + (~y & 3);
533#endif 540#endif
534#endif /* LCD_PIXELFORMAT */ 541#endif /* LCD_PIXELFORMAT */
535 unsigned char *dst_row = &_grey_info.data[idx].value; 542 unsigned char *dst_row = _grey_info.values + idx;
536 unsigned char *src_row = src; 543 unsigned char *src_row = src;
537 unsigned char *src_end = src + width; 544 unsigned char *src_end = src + width;
538 545
@@ -684,8 +691,8 @@ static void grey_screendump_hook(int fd)
684 for (i = 0; i < 4; i++) 691 for (i = 0; i < 4; i++)
685 linebuf[x + i] = BMP_FIXEDCOLORS + *src++; 692 linebuf[x + i] = BMP_FIXEDCOLORS + *src++;
686#else 693#else
687 unsigned char *src = &_grey_info.data[_GREY_MULUQ(_grey_info.width, 694 unsigned char *src = _grey_info.values
688 gy) + gx].value; 695 + _GREY_MULUQ(_grey_info.width, gy) + gx;
689 for (i = 0; i < 4; i++) 696 for (i = 0; i < 4; i++)
690 { 697 {
691 linebuf[x + i] = BMP_FIXEDCOLORS + *src; 698 linebuf[x + i] = BMP_FIXEDCOLORS + *src;
@@ -722,8 +729,8 @@ static void grey_screendump_hook(int fd)
722 gy) + gx]; 729 gy) + gx];
723#else 730#else
724 linebuf[x] = BMP_FIXEDCOLORS 731 linebuf[x] = BMP_FIXEDCOLORS
725 + _grey_info.data[_GREY_MULUQ(_grey_info.width, 732 + _grey_info.values[_GREY_MULUQ(_grey_info.width,
726 gy & ~7) + (gx << 3) + (~gy & 7)].value; 733 gy & ~7) + (gx << 3) + (~gy & 7)];
727#endif 734#endif
728 } 735 }
729 else 736 else
@@ -749,8 +756,8 @@ static void grey_screendump_hook(int fd)
749 gy) + gx]; 756 gy) + gx];
750#else 757#else
751 linebuf[x] = BMP_FIXEDCOLORS 758 linebuf[x] = BMP_FIXEDCOLORS
752 + _grey_info.data[_GREY_MULUQ(_grey_info.width, 759 + _grey_info.values[_GREY_MULUQ(_grey_info.width,
753 gy & ~3) + (gx << 2) + (~gy & 7)].value; 760 gy & ~3) + (gx << 2) + (~gy & 3)];
754#endif 761#endif
755 } 762 }
756 else 763 else
diff --git a/apps/plugins/lib/grey_draw.c b/apps/plugins/lib/grey_draw.c
index e243b5fbce..ccb8deae7b 100644
--- a/apps/plugins/lib/grey_draw.c
+++ b/apps/plugins/lib/grey_draw.c
@@ -601,17 +601,10 @@ void grey_ub_gray_bitmap_part(const unsigned char *src, int src_x, int src_y,
601void grey_ub_clear_display(void) 601void grey_ub_clear_display(void)
602{ 602{
603 int value = (_grey_info.drawmode & DRMODE_INVERSEVID) ? 603 int value = (_grey_info.drawmode & DRMODE_INVERSEVID) ?
604 _grey_info.fg_val : _grey_info.bg_val; 604 _grey_info.fg_val : _grey_info.bg_val;
605 unsigned char *dst = &_grey_info.data[0].value; 605
606 unsigned char *dst_end = dst + sizeof(struct grey_data) 606 _grey_rb->memset(_grey_info.values, value,
607 * _GREY_MULUQ(_grey_info.width, _grey_info.height); 607 _GREY_MULUQ(_grey_info.width, _grey_info.height));
608
609 do
610 {
611 *dst = value;
612 dst += sizeof(struct grey_data);
613 }
614 while (dst < dst_end);
615} 608}
616 609
617/* Draw a partial greyscale bitmap, canonical format */ 610/* Draw a partial greyscale bitmap, canonical format */
@@ -654,7 +647,7 @@ void grey_ub_gray_bitmap_part(const unsigned char *src, int src_x, int src_y,
654 int idx = _GREY_MULUQ(_grey_info.width, y & ~3) + (x << 2) + (~y & 3); 647 int idx = _GREY_MULUQ(_grey_info.width, y & ~3) + (x << 2) + (~y & 3);
655#endif 648#endif
656#endif /* LCD_PIXELFORMAT */ 649#endif /* LCD_PIXELFORMAT */
657 unsigned char *dst_row = &_grey_info.data[idx].value; 650 unsigned char *dst_row = _grey_info.values + idx;
658 const unsigned char *src_row = src; 651 const unsigned char *src_row = src;
659 const unsigned char *src_end = src + width; 652 const unsigned char *src_end = src + width;
660 653
diff --git a/apps/plugins/lib/grey_scroll.c b/apps/plugins/lib/grey_scroll.c
index 80496e7706..4a18d7d29e 100644
--- a/apps/plugins/lib/grey_scroll.c
+++ b/apps/plugins/lib/grey_scroll.c
@@ -169,7 +169,7 @@ void grey_ub_scroll_left(int count)
169 idx = _GREY_MULUQ(_grey_info.width, y & ~3) + (~y & 3); 169 idx = _GREY_MULUQ(_grey_info.width, y & ~3) + (~y & 3);
170#endif 170#endif
171#endif /* LCD_PIXELFORMAT */ 171#endif /* LCD_PIXELFORMAT */
172 dst = &_grey_info.data[idx].value; 172 dst = _grey_info.values + idx;
173 src = dst + count * _GREY_X_ADVANCE; 173 src = dst + count * _GREY_X_ADVANCE;
174 end = dst + _grey_info.width * _GREY_X_ADVANCE; 174 end = dst + _grey_info.width * _GREY_X_ADVANCE;
175 175
@@ -213,7 +213,7 @@ void grey_ub_scroll_right(int count)
213 idx = _GREY_MULUQ(_grey_info.width, y & ~3) + (~y & 3); 213 idx = _GREY_MULUQ(_grey_info.width, y & ~3) + (~y & 3);
214#endif 214#endif
215#endif /* LCD_PIXELFORMAT */ 215#endif /* LCD_PIXELFORMAT */
216 start = &_grey_info.data[idx].value; 216 start = _grey_info.values + idx;
217 dst = start + _grey_info.width * _GREY_X_ADVANCE; 217 dst = start + _grey_info.width * _GREY_X_ADVANCE;
218 src = dst - count * _GREY_X_ADVANCE; 218 src = dst - count * _GREY_X_ADVANCE;
219 219
@@ -259,8 +259,8 @@ void grey_ub_scroll_up(int count)
259 is = _GREY_MULUQ(_grey_info.width, ys & ~3) + (~ys & 3); 259 is = _GREY_MULUQ(_grey_info.width, ys & ~3) + (~ys & 3);
260#endif 260#endif
261#endif /* LCD_PIXELFORMAT */ 261#endif /* LCD_PIXELFORMAT */
262 dst = &_grey_info.data[id].value; 262 dst = _grey_info.values + id;
263 src = &_grey_info.data[is].value; 263 src = _grey_info.values + is;
264 dst_end = dst + _grey_info.width * _GREY_X_ADVANCE; 264 dst_end = dst + _grey_info.width * _GREY_X_ADVANCE;
265 265
266 do 266 do
@@ -282,7 +282,7 @@ void grey_ub_scroll_up(int count)
282 id = _GREY_MULUQ(_grey_info.width, yd & ~3) + (~yd & 3); 282 id = _GREY_MULUQ(_grey_info.width, yd & ~3) + (~yd & 3);
283#endif 283#endif
284#endif /* LCD_PIXELFORMAT */ 284#endif /* LCD_PIXELFORMAT */
285 dst = &_grey_info.data[id].value; 285 dst = _grey_info.values + id;
286 dst_end = dst + _grey_info.width * _GREY_X_ADVANCE; 286 dst_end = dst + _grey_info.width * _GREY_X_ADVANCE;
287 287
288 do 288 do
@@ -320,8 +320,8 @@ void grey_ub_scroll_down(int count)
320 is = _GREY_MULUQ(_grey_info.width, ys & ~3) + (~ys & 3); 320 is = _GREY_MULUQ(_grey_info.width, ys & ~3) + (~ys & 3);
321#endif 321#endif
322#endif /* LCD_PIXELFORMAT */ 322#endif /* LCD_PIXELFORMAT */
323 dst = &_grey_info.data[id].value; 323 dst = _grey_info.values + id;
324 src = &_grey_info.data[is].value; 324 src = _grey_info.values + is;
325 dst_end = dst + _grey_info.width * _GREY_X_ADVANCE; 325 dst_end = dst + _grey_info.width * _GREY_X_ADVANCE;
326 326
327 do 327 do
@@ -343,7 +343,7 @@ void grey_ub_scroll_down(int count)
343 id = _GREY_MULUQ(_grey_info.width, yd & ~3) + (~yd & 3); 343 id = _GREY_MULUQ(_grey_info.width, yd & ~3) + (~yd & 3);
344#endif 344#endif
345#endif /* LCD_PIXELFORMAT */ 345#endif /* LCD_PIXELFORMAT */
346 dst = &_grey_info.data[id].value; 346 dst = _grey_info.values + id;
347 dst_end = dst + _grey_info.width * _GREY_X_ADVANCE; 347 dst_end = dst + _grey_info.width * _GREY_X_ADVANCE;
348 348
349 do 349 do
diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h
index 57c9b1d3b8..669ef67f02 100644
--- a/firmware/export/lcd.h
+++ b/firmware/export/lcd.h
@@ -131,13 +131,9 @@ extern void lcd_yuv_blit(unsigned char * const src[3],
131 int src_x, int src_y, int stride, 131 int src_x, int src_y, int stride,
132 int x, int y, int width, int height); 132 int x, int y, int width, int height);
133#else 133#else
134struct grey_data { 134extern void lcd_grey_phase_blit(unsigned char *values, unsigned char *phases,
135 unsigned char phase; /* SH1 uses it signed (doesn't matter for high level) */ 135 int bx, int by, int bwidth, int bheight,
136 unsigned char value; /* 0..128 are allowed */ 136 int stride);
137} __attribute__((packed));
138extern void lcd_grey_data(const struct grey_data *data, int count); /* private */
139extern void lcd_grey_phase_blit(const struct grey_data *data, int bx, int by,
140 int bwidth, int bheight, int stride);
141#endif 137#endif
142 138
143/* performance function */ 139/* performance function */
diff --git a/firmware/target/arm/ipod/lcd-gray.c b/firmware/target/arm/ipod/lcd-gray.c
index c7f4074c0b..5734480bee 100644
--- a/firmware/target/arm/ipod/lcd-gray.c
+++ b/firmware/target/arm/ipod/lcd-gray.c
@@ -301,118 +301,88 @@ void lcd_blit(const unsigned char* data, int bx, int y, int bwidth,
301 301
302/* Performance function that works with an external buffer 302/* Performance function that works with an external buffer
303 note that bx and bwidth are in 8-pixel units! */ 303 note that bx and bwidth are in 8-pixel units! */
304void lcd_grey_phase_blit(const struct grey_data *data, int bx, int y, 304void lcd_grey_phase_blit(unsigned char *values, unsigned char *phases,
305 int bwidth, int height, int stride) 305 int bx, int y, int bwidth, int height, int stride)
306{ 306{
307 const struct grey_data *addr; 307 unsigned char *val, *ph;
308 int width; 308 int bw;
309 309
310 while (height--) { 310 while (height--) {
311 lcd_cmd_and_data(R_RAM_ADDR_SET, (y++ << 5) + addr_offset - bx); 311 lcd_cmd_and_data(R_RAM_ADDR_SET, (y++ << 5) + addr_offset - bx);
312 lcd_prepare_cmd(R_RAM_DATA); 312 lcd_prepare_cmd(R_RAM_DATA);
313 313
314 addr = data; 314 val = values;
315 width = bwidth; 315 ph = phases;
316 bw = bwidth;
316 asm volatile ( 317 asm volatile (
317 "10: \n" 318 "10: \n"
318 "ldmia %[addr]!, {r0-r3} \n" /* r0 = v1p1v0p0 ... */ 319 "ldmia %[ph], {r0-r1} \n" /* Fetch 8 pixel phases */
320 "ldmia %[val]!, {r2-r3} \n" /* Fetch 8 pixel values */
319#ifdef IPOD_MINI2G 321#ifdef IPOD_MINI2G
320 "mov r5, #0x7600 \n" 322 "mov r4, #0x7600 \n"
321#else 323#else
322 "mov r5, #0 \n" 324 "mov r4, #0 \n"
323#endif 325#endif
324 326 "tst r0, #0x80 \n"
325 "and r4, r0, %[mask] \n" /* r4 = --p1--p0 */ 327 "orreq r4, r4, #0xc0 \n"
326 "and r0, %[mask], r0, lsr #8 \n" /* r0 = --v1--v0 */ 328 "tst r0, #0x8000 \n"
327 329 "orreq r4, r4, #0x30 \n"
328 "tst r4, #0x80 \n" 330 "tst r0, #0x800000 \n"
329 "orreq r5, r5, #0xc0 \n" 331 "orreq r4, r4, #0x0c \n"
330 "tst r4, #0x800000 \n" 332 "tst r0, #0x80000000 \n"
331 "orreq r5, r5, #0x30 \n" 333 "orreq r4, r4, #0x03 \n"
332 "bic r4, r4, %[clbt] \n" 334 "bic r0, r0, %[clbt] \n"
333 335 "add r0, r0, r2 \n"
334 "add r4, r0, r4 \n" /* p0 += v0; p1 += v1; */
335 "strb r4, [%[addr], #-16] \n"
336 "mov r4, r4, lsr #16 \n"
337 "strb r4, [%[addr], #-14] \n"
338
339 "and r4, r1, %[mask] \n"
340 "and r1, %[mask], r1, lsr #8 \n"
341
342 "tst r4, #0x80 \n"
343 "orreq r5, r5, #0x0c \n"
344 "tst r4, #0x800000 \n"
345 "orreq r5, r5, #0x03 \n"
346 "bic r4, r4, %[clbt] \n"
347
348 "add r4, r1, r4 \n"
349 "strb r4, [%[addr], #-12] \n"
350 "mov r4, r4, lsr #16 \n"
351 "strb r4, [%[addr], #-10] \n"
352 336
353#ifdef IPOD_MINI2G 337#ifdef IPOD_MINI2G
354 "mov r5, r5, lsl #8 \n" 338 "mov r4, r4, lsl #8 \n"
355#else 339#else
356 "1: \n" 340 "1: \n"
357 "ldr r4, [%[lcdb]] \n" 341 "ldr r2, [%[lcdb]] \n"
358 "tst r4, #0x8000 \n" 342 "tst r2, #0x8000 \n"
359 "bne 1b \n" 343 "bne 1b \n"
360 344
361 "str r5, [%[lcdb], #0x10] \n" 345 "str r4, [%[lcdb], #0x10] \n"
362 "mov r5, #0 \n" 346 "mov r4, #0 \n"
363#endif 347#endif
364 348
365 "and r4, r2, %[mask] \n" 349 "tst r1, #0x80 \n"
366 "and r2, %[mask], r2, lsr #8 \n" 350 "orreq r4, r4, #0xc0 \n"
367 351 "tst r1, #0x8000 \n"
368 "tst r4, #0x80 \n" 352 "orreq r4, r4, #0x30 \n"
369 "orreq r5, r5, #0xc0 \n" 353 "tst r1, #0x800000 \n"
370 "tst r4, #0x800000 \n" 354 "orreq r4, r4, #0x0c \n"
371 "orreq r5, r5, #0x30 \n" 355 "tst r1, #0x80000000 \n"
372 "bic r4, r4, %[clbt] \n" 356 "orreq r4, r4, #0x03 \n"
373 357 "bic r1, r1, %[clbt] \n"
374 "add r4, r2, r4 \n" 358 "add r1, r1, r3 \n"
375 "strb r4, [%[addr], #-8] \n" 359
376 "mov r4, r4, lsr #16 \n" 360 "stmia %[ph]!, {r0-r1} \n"
377 "strb r4, [%[addr], #-6] \n" 361
378
379 "and r4, r3, %[mask] \n"
380 "and r3, %[mask], r3, lsr #8 \n"
381
382 "tst r4, #0x80 \n"
383 "orreq r5, r5, #0x0c \n"
384 "tst r4, #0x800000 \n"
385 "orreq r5, r5, #0x03 \n"
386 "bic r4, r4, %[clbt] \n"
387
388 "add r4, r3, r4 \n"
389 "strb r4, [%[addr], #-4] \n"
390 "mov r4, r4, lsr #16 \n"
391 "strb r4, [%[addr], #-2] \n"
392
393 "1: \n" 362 "1: \n"
394 "ldr r4, [%[lcdb]] \n" 363 "ldr r2, [%[lcdb]] \n"
395 "tst r4, #0x8000 \n" 364 "tst r2, #0x8000 \n"
396 "bne 1b \n" 365 "bne 1b \n"
397#ifdef IPOD_MINI2G 366#ifdef IPOD_MINI2G
398 "str r5, [%[lcdb], #0x08] \n" 367 "str r4, [%[lcdb], #0x08] \n"
399#else 368#else
400 "str r5, [%[lcdb], #0x10] \n" 369 "str r4, [%[lcdb], #0x10] \n"
401#endif 370#endif
402 371
403 "subs %[wdth], %[wdth], #1 \n" 372 "subs %[bw], %[bw], #1 \n"
404 "bne 10b \n" 373 "bne 10b \n"
405 : /* outputs */ 374 : /* outputs */
406 [addr]"+r"(addr), 375 [val]"+r"(val),
407 [wdth]"+r"(width) 376 [ph] "+r"(ph),
377 [bw] "+r"(bw)
408 : /* inputs */ 378 : /* inputs */
409 [mask]"r"(0x00ff00ff), 379 [clbt]"r"(0x80808080),
410 [clbt]"r"(0x00800080),
411 [lcdb]"r"(LCD1_BASE) 380 [lcdb]"r"(LCD1_BASE)
412 : /* clobbers */ 381 : /* clobbers */
413 "r0", "r1", "r2", "r3", "r4", "r5" 382 "r0", "r1", "r2", "r3", "r4"
414 ); 383 );
415 data += stride; 384 values += stride;
385 phases += stride;
416 } 386 }
417} 387}
418 388
diff --git a/firmware/target/coldfire/iaudio/m5/lcd-as-m5.S b/firmware/target/coldfire/iaudio/m5/lcd-as-m5.S
index 7e89815ec8..0ec98e4589 100644
--- a/firmware/target/coldfire/iaudio/m5/lcd-as-m5.S
+++ b/firmware/target/coldfire/iaudio/m5/lcd-as-m5.S
@@ -88,57 +88,146 @@ lcd_write_data:
88 .type lcd_grey_data,@function 88 .type lcd_grey_data,@function
89 89
90lcd_grey_data: 90lcd_grey_data:
91 lea.l (-4*4, %sp), %sp 91 lea.l (-9*4, %sp), %sp
92 movem.l %d2-%d5, (%sp) 92 movem.l %d2-%d5/%a2-%a6, (%sp) /* free some registers */
93 movem.l (4*4+4, %sp), %a0-%a1 /* Data pointer */ 93 movem.l (9*4+4, %sp), %a0-%a2 /* values, phases, length */
94 move.l %a1, %d0 /* Length */ 94 lea.l (%a1, %a2.l*4), %a2 /* end address */
95 lea 0xf0008002, %a1 /* LCD data port */ 95 lea 0xf0008002, %a3 /* LCD data port */
96 move.l #0xff00ff00, %d2 /* mask for splitting value/phase pairs */ 96
97 97 moveq.l #15, %d3
98.greyloop: 98 add.l %a1, %d3
99 movem.l (%a0), %d4-%d5 /* fetch 4 pixel phase/value pairs at once */ 99 and.l #0xfffffff0, %d3 /* first line bound */
100 /* %d4 = p0v0p1v1, %d5 = p2v2p3v3 */ 100 move.l %a2, %d1
101 move.l %d2, %d3 /* copy mask */ 101 and.l #0xfffffff0, %d1 /* last line bound */
102 and.l %d4, %d3 /* %d3 = p0--p1-- */ 102 cmp.l %d3, %d1
103 eor.l %d3, %d4 /* %d4 = --v0--v1 */ 103 bls.w .g_tloop /* no lines to copy - jump to tail loop */
104 lsr.l #8, %d3 /* %d3 = --p0--p1 */ 104 cmp.l %a1, %d0
105 105 bls.s .g_lloop /* no head blocks - jump to line loop */
106 bclr.l #23, %d3 /* Z = !(p0 & 0x80); p0 &= ~0x80; */ 106
107 seq.b %d1 /* %d1 = ........................00000000 */ 107.g_hloop:
108 lsl.l #2, %d1 /* %d1 = ......................00000000.. */ 108 move.l (%a1), %d2 /* fetch 4 pixel phases */
109 bclr.l #7, %d3 /* Z = !(p1 & 0x80); p1 &= ~0x80; */ 109
110 seq.b %d1 /* %d1 = ......................0011111111 */ 110 bclr.l #31, %d2 /* Z = !(p0 & 0x80); p0 &= ~0x80; */
111 lsl.l #2, %d1 /* %d1 = ....................0011111111.. */ 111 seq.b %d0 /* %d0 = ........................00000000 */
112 lsl.l #2, %d0 /* %d0 = ......................00000000.. */
113 bclr.l #23, %d2 /* Z = !(p1 & 0x80); p1 &= ~0x80; */
114 seq.b %d0 /* %d0 = ......................0011111111 */
115 lsl.l #2, %d0 /* %d0 = ....................0011111111.. */
116 bclr.l #15, %d2 /* Z = !(p2 & 0x80); p2 &= ~0x80; */
117 seq.b %d0 /* %d0 = ....................001122222222 */
118 lsl.l #2, %d0 /* %d0 = ..................001122222222.. */
119 bclr.l #7, %d2 /* Z = !(p3 & 0x80); p3 &= ~0x80; */
120 seq.b %d0 /* %d0 = ..................00112233333333 */
121 lsr.l #6, %d0 /* %d0 = ........................00112233 */
122 move.w %d0, (%a3) /* write pixel block */
123
124 add.l (%a0)+, %d2 /* add 4 pixel values to the phases */
125 move.l %d2, (%a1)+ /* store new phases, advance pointer */
126
127 cmp.l %a1, %d3 /* go up to first line bound */
128 bhi.s .g_hloop
129
130.g_lloop:
131 movem.l (%a1), %d2-%d5
132
133 bclr.l #31, %d2
134 seq.b %d0
135 lsl.l #2, %d0
136 bclr.l #23, %d2
137 seq.b %d0
138 lsl.l #2, %d0
139 bclr.l #15, %d2
140 seq.b %d0
141 lsl.l #2, %d0
142 bclr.l #7, %d2
143 seq.b %d0
144 lsr.l #6, %d0
145 move.w %d0, (%a3)
146
147 bclr.l #31, %d3
148 seq.b %d0
149 lsl.l #2, %d0
150 bclr.l #23, %d3
151 seq.b %d0
152 lsl.l #2, %d0
153 bclr.l #15, %d3
154 seq.b %d0
155 lsl.l #2, %d0
156 bclr.l #7, %d3
157 seq.b %d0
158 lsr.l #6, %d0
159 move.w %d0, (%a3)
112 160
113 add.l %d4, %d3 /* p0 += v0; p1 += v1; */ 161 bclr.l #31, %d4
114 move.b %d3, (2, %a0) /* store p1 */ 162 seq.b %d0
115 swap %d3 163 lsl.l #2, %d0
116 move.b %d3, (%a0) /* store p0 */ 164 bclr.l #23, %d4
117 165 seq.b %d0
118 move.l %d2, %d3 /* copy mask */ 166 lsl.l #2, %d0
119 and.l %d5, %d3 /* %d3 = p2--p3-- */ 167 bclr.l #15, %d4
120 eor.l %d3, %d5 /* %d5 = --v2--v3 */ 168 seq.b %d0
121 lsr.l #8, %d3 /* %d3 = --p2--p3 */ 169 lsl.l #2, %d0
122 170 bclr.l #7, %d4
123 bclr.l #23, %d3 /* Z = !(p2 & 0x80); p2 &= ~0x80; */ 171 seq.b %d0
124 seq.b %d1 /* %d1 = ....................001122222222 */ 172 lsr.l #6, %d0
125 lsl.l #2, %d1 /* %d1 = ..................001122222222.. */ 173 move.w %d0, (%a3)
126 bclr.l #7, %d3 /* Z = !(p3 & 0x80); p3 &= ~0x80; */ 174
127 seq.b %d1 /* %d1 = ..................00112233333333 */ 175 bclr.l #31, %d5
128 lsr.l #6, %d1 /* %d1 = ........................00112233 */ 176 seq.b %d0
129 177 lsl.l #2, %d0
130 add.l %d5, %d3 /* p2 += v2; p3 += v3; */ 178 bclr.l #23, %d5
131 move.b %d3, (6, %a0) /* store p3 */ 179 seq.b %d0
132 swap %d3 180 lsl.l #2, %d0
133 move.b %d3, (4, %a0) /* store p2 */ 181 bclr.l #15, %d5
134 182 seq.b %d0
135 move.w %d1, (%a1) /* write pixel block */ 183 lsl.l #2, %d0
136 addq.l #8, %a0 /* advance address pointer */ 184 bclr.l #7, %d5
137 subq.l #1, %d0 /* any blocks left? */ 185 seq.b %d0
138 bne.b .greyloop 186 lsr.l #6, %d0
139 187 move.w %d0, (%a3)
140 movem.l (%sp), %d2-%d5 188
141 lea.l (4*4, %sp), %sp 189 movem.l (%a0), %d0/%a4-%a6
190 lea.l (16, %a0), %a0
191 add.l %d0, %d2
192 add.l %a4, %d3
193 add.l %a5, %d4
194 add.l %a6, %d5
195 movem.l %d2-%d5, (%a1)
196 lea.l (16, %a1), %a1
197
198 cmp.l %a1, %d1 /* go up to last line bound */
199 bhi.w .g_lloop
200
201 cmp.l %a1, %a2
202 bls.s .g_no_tail
203
204.g_tloop:
205 move.l (%a1), %d2
206
207 bclr.l #31, %d2
208 seq.b %d0
209 lsl.l #2, %d0
210 bclr.l #23, %d2
211 seq.b %d0
212 lsl.l #2, %d0
213 bclr.l #15, %d2
214 seq.b %d0
215 lsl.l #2, %d0
216 bclr.l #7, %d2
217 seq.b %d0
218 lsr.l #6, %d0
219 move.w %d0, (%a3)
220
221 add.l (%a0)+, %d2 /* go up to end address */
222 move.l %d2, (%a1)+
223
224 cmp.l %a1, %a2
225 bhi.s .g_tloop
226
227.g_no_tail:
228 movem.l (%sp), %d2-%d5/%a2-%a6 /* restore registers */
229 lea.l (9*4, %sp), %sp
142 rts 230 rts
231
143.gd_end: 232.gd_end:
144 .size lcd_grey_data,.gd_end-lcd_grey_data 233 .size lcd_grey_data,.gd_end-lcd_grey_data
diff --git a/firmware/target/coldfire/iaudio/m5/lcd-m5.c b/firmware/target/coldfire/iaudio/m5/lcd-m5.c
index 4f963795c7..be9d5a39b8 100644
--- a/firmware/target/coldfire/iaudio/m5/lcd-m5.c
+++ b/firmware/target/coldfire/iaudio/m5/lcd-m5.c
@@ -171,10 +171,13 @@ void lcd_blit(const unsigned char* data, int x, int by, int width,
171 } 171 }
172} 172}
173 173
174/* Helper function for lcd_grey_phase_blit(). */
175void lcd_grey_data(unsigned char *values, unsigned char *phases, int count);
176
174/* Performance function that works with an external buffer 177/* Performance function that works with an external buffer
175 note that by and bheight are in 4-pixel units! */ 178 note that by and bheight are in 4-pixel units! */
176void lcd_grey_phase_blit(const struct grey_data *data, int x, int by, 179void lcd_grey_phase_blit(unsigned char *values, unsigned char *phases,
177 int width, int bheight, int stride) 180 int x, int by, int width, int bheight, int stride)
178{ 181{
179 stride <<= 2; /* 4 pixels per block */ 182 stride <<= 2; /* 4 pixels per block */
180 while (bheight--) 183 while (bheight--)
@@ -182,8 +185,9 @@ void lcd_grey_phase_blit(const struct grey_data *data, int x, int by,
182 lcd_write_command_ex(LCD_CNTL_PAGE, by++, -1); 185 lcd_write_command_ex(LCD_CNTL_PAGE, by++, -1);
183 lcd_write_command_ex(LCD_CNTL_COLUMN, x, -1); 186 lcd_write_command_ex(LCD_CNTL_COLUMN, x, -1);
184 lcd_write_command(LCD_CNTL_DATA_WRITE); 187 lcd_write_command(LCD_CNTL_DATA_WRITE);
185 lcd_grey_data(data, width); 188 lcd_grey_data(values, phases, width);
186 data += stride; 189 values += stride;
190 phases += stride;
187 } 191 }
188} 192}
189 193
diff --git a/firmware/target/coldfire/iriver/h100/lcd-as-h100.S b/firmware/target/coldfire/iriver/h100/lcd-as-h100.S
index df410fa379..776e22a6c4 100644
--- a/firmware/target/coldfire/iriver/h100/lcd-as-h100.S
+++ b/firmware/target/coldfire/iriver/h100/lcd-as-h100.S
@@ -100,59 +100,148 @@ lcd_write_data:
100 .type lcd_grey_data,@function 100 .type lcd_grey_data,@function
101 101
102lcd_grey_data: 102lcd_grey_data:
103 lea.l (-4*4, %sp), %sp 103 lea.l (-9*4, %sp), %sp
104 movem.l %d2-%d5, (%sp) 104 movem.l %d2-%d5/%a2-%a6, (%sp) /* free some registers */
105 movem.l (4*4+4, %sp), %a0-%a1 /* Data pointer */ 105 movem.l (9*4+4, %sp), %a0-%a2 /* values, phases, length */
106 move.l %a1, %d0 /* Length */ 106 lea.l (%a1, %a2.l*4), %a2 /* end address */
107 moveq #8, %d1 107 moveq #8, %d1
108 or.l %d1, (MBAR2+0xb4) /* A0 = 1 (data) */ 108 or.l %d1, (MBAR2+0xb4) /* A0 = 1 (data) */
109 lea 0xf0000000, %a1 /* LCD data port */ 109 lea 0xf0000000, %a3 /* LCD data port */
110 move.l #0xff00ff00, %d2 /* mask for splitting value/phase pairs */ 110
111 111 moveq.l #15, %d3
112.greyloop: 112 add.l %a1, %d3
113 movem.l (%a0), %d4-%d5 /* fetch 4 pixel phase/value pairs at once */ 113 and.l #0xfffffff0, %d3 /* first line bound */
114 /* %d4 = p0v0p1v1, %d5 = p2v2p3v3 */ 114 move.l %a2, %d1
115 move.l %d2, %d3 /* copy mask */ 115 and.l #0xfffffff0, %d1 /* last line bound */
116 and.l %d4, %d3 /* %d3 = p0--p1-- */ 116 cmp.l %d3, %d1
117 eor.l %d3, %d4 /* %d4 = --v0--v1 */ 117 bls.w .g_tloop /* no lines to copy - jump to tail loop */
118 lsr.l #8, %d3 /* %d3 = --p0--p1 */ 118 cmp.l %a1, %d0
119 119 bls.s .g_lloop /* no head blocks - jump to line loop */
120 bclr.l #23, %d3 /* Z = !(p0 & 0x80); p0 &= ~0x80; */ 120
121 seq.b %d1 /* %d1 = ........................00000000 */ 121.g_hloop:
122 lsl.l #2, %d1 /* %d1 = ......................00000000.. */ 122 move.l (%a1), %d2 /* fetch 4 pixel phases */
123 bclr.l #7, %d3 /* Z = !(p1 & 0x80); p1 &= ~0x80; */ 123
124 seq.b %d1 /* %d1 = ......................0011111111 */ 124 bclr.l #31, %d2 /* Z = !(p0 & 0x80); p0 &= ~0x80; */
125 lsl.l #2, %d1 /* %d1 = ....................0011111111.. */ 125 seq.b %d0 /* %d0 = ........................00000000 */
126 lsl.l #2, %d0 /* %d0 = ......................00000000.. */
127 bclr.l #23, %d2 /* Z = !(p1 & 0x80); p1 &= ~0x80; */
128 seq.b %d0 /* %d0 = ......................0011111111 */
129 lsl.l #2, %d0 /* %d0 = ....................0011111111.. */
130 bclr.l #15, %d2 /* Z = !(p2 & 0x80); p2 &= ~0x80; */
131 seq.b %d0 /* %d0 = ....................001122222222 */
132 lsl.l #2, %d0 /* %d0 = ..................001122222222.. */
133 bclr.l #7, %d2 /* Z = !(p3 & 0x80); p3 &= ~0x80; */
134 seq.b %d0 /* %d0 = ..................00112233333333 */
135 lsr.l #6, %d0 /* %d0 = ........................00112233 */
136 move.w %d0, (%a3) /* write pixel block */
137
138 add.l (%a0)+, %d2 /* add 4 pixel values to the phases */
139 move.l %d2, (%a1)+ /* store new phases, advance pointer */
140
141 cmp.l %a1, %d3 /* go up to first line bound */
142 bhi.s .g_hloop
143
144.g_lloop:
145 movem.l (%a1), %d2-%d5
126 146
127 add.l %d4, %d3 /* p0 += v0; p1 += v1; */ 147 bclr.l #31, %d2
128 move.b %d3, (2, %a0) /* store p1 */ 148 seq.b %d0
129 swap %d3 149 lsl.l #2, %d0
130 move.b %d3, (%a0) /* store p0 */ 150 bclr.l #23, %d2
131 151 seq.b %d0
132 move.l %d2, %d3 /* copy mask */ 152 lsl.l #2, %d0
133 and.l %d5, %d3 /* %d3 = p2--p3-- */ 153 bclr.l #15, %d2
134 eor.l %d3, %d5 /* %d5 = --v2--v3 */ 154 seq.b %d0
135 lsr.l #8, %d3 /* %d3 = --p2--p3 */ 155 lsl.l #2, %d0
136 156 bclr.l #7, %d2
137 bclr.l #23, %d3 /* Z = !(p2 & 0x80); p2 &= ~0x80; */ 157 seq.b %d0
138 seq.b %d1 /* %d1 = ....................001122222222 */ 158 lsr.l #6, %d0
139 lsl.l #2, %d1 /* %d1 = ..................001122222222.. */ 159 move.w %d0, (%a3)
140 bclr.l #7, %d3 /* Z = !(p3 & 0x80); p3 &= ~0x80; */ 160
141 seq.b %d1 /* %d1 = ..................00112233333333 */ 161 bclr.l #31, %d3
142 lsr.l #6, %d1 /* %d1 = ........................00112233 */ 162 seq.b %d0
143 163 lsl.l #2, %d0
144 add.l %d5, %d3 /* p2 += v2; p3 += v3; */ 164 bclr.l #23, %d3
145 move.b %d3, (6, %a0) /* store p3 */ 165 seq.b %d0
146 swap %d3 166 lsl.l #2, %d0
147 move.b %d3, (4, %a0) /* store p2 */ 167 bclr.l #15, %d3
148 168 seq.b %d0
149 move.w %d1, (%a1) /* write pixel block */ 169 lsl.l #2, %d0
150 addq.l #8, %a0 /* advance address pointer */ 170 bclr.l #7, %d3
151 subq.l #1, %d0 /* any blocks left? */ 171 seq.b %d0
152 bne.b .greyloop 172 lsr.l #6, %d0
153 173 move.w %d0, (%a3)
154 movem.l (%sp), %d2-%d5 174
155 lea.l (4*4, %sp), %sp 175 bclr.l #31, %d4
176 seq.b %d0
177 lsl.l #2, %d0
178 bclr.l #23, %d4
179 seq.b %d0
180 lsl.l #2, %d0
181 bclr.l #15, %d4
182 seq.b %d0
183 lsl.l #2, %d0
184 bclr.l #7, %d4
185 seq.b %d0
186 lsr.l #6, %d0
187 move.w %d0, (%a3)
188
189 bclr.l #31, %d5
190 seq.b %d0
191 lsl.l #2, %d0
192 bclr.l #23, %d5
193 seq.b %d0
194 lsl.l #2, %d0
195 bclr.l #15, %d5
196 seq.b %d0
197 lsl.l #2, %d0
198 bclr.l #7, %d5
199 seq.b %d0
200 lsr.l #6, %d0
201 move.w %d0, (%a3)
202
203 movem.l (%a0), %d0/%a4-%a6
204 lea.l (16, %a0), %a0
205 add.l %d0, %d2
206 add.l %a4, %d3
207 add.l %a5, %d4
208 add.l %a6, %d5
209 movem.l %d2-%d5, (%a1)
210 lea.l (16, %a1), %a1
211
212 cmp.l %a1, %d1 /* go up to last line bound */
213 bhi.w .g_lloop
214
215 cmp.l %a1, %a2
216 bls.s .g_no_tail
217
218.g_tloop:
219 move.l (%a1), %d2
220
221 bclr.l #31, %d2
222 seq.b %d0
223 lsl.l #2, %d0
224 bclr.l #23, %d2
225 seq.b %d0
226 lsl.l #2, %d0
227 bclr.l #15, %d2
228 seq.b %d0
229 lsl.l #2, %d0
230 bclr.l #7, %d2
231 seq.b %d0
232 lsr.l #6, %d0
233 move.w %d0, (%a3)
234
235 add.l (%a0)+, %d2
236 move.l %d2, (%a1)+
237
238 cmp.l %a1, %a2 /* go up to end address */
239 bhi.s .g_tloop
240
241.g_no_tail:
242 movem.l (%sp), %d2-%d5/%a2-%a6 /* restore registers */
243 lea.l (9*4, %sp), %sp
156 rts 244 rts
245
157.gd_end: 246.gd_end:
158 .size lcd_grey_data,.gd_end-lcd_grey_data 247 .size lcd_grey_data,.gd_end-lcd_grey_data
diff --git a/firmware/target/coldfire/iriver/h100/lcd-h100.c b/firmware/target/coldfire/iriver/h100/lcd-h100.c
index c17de952c3..2ba19255da 100644
--- a/firmware/target/coldfire/iriver/h100/lcd-h100.c
+++ b/firmware/target/coldfire/iriver/h100/lcd-h100.c
@@ -180,10 +180,13 @@ void lcd_blit(const unsigned char* data, int x, int by, int width,
180 } 180 }
181} 181}
182 182
183/* Helper function for lcd_grey_phase_blit(). */
184void lcd_grey_data(unsigned char *values, unsigned char *phases, int count);
185
183/* Performance function that works with an external buffer 186/* Performance function that works with an external buffer
184 note that by and bheight are in 4-pixel units! */ 187 note that by and bheight are in 4-pixel units! */
185void lcd_grey_phase_blit(const struct grey_data *data, int x, int by, 188void lcd_grey_phase_blit(unsigned char *values, unsigned char *phases,
186 int width, int bheight, int stride) 189 int x, int by, int width, int bheight, int stride)
187{ 190{
188 stride <<= 2; /* 4 pixels per block */ 191 stride <<= 2; /* 4 pixels per block */
189 while (bheight--) 192 while (bheight--)
@@ -191,8 +194,9 @@ void lcd_grey_phase_blit(const struct grey_data *data, int x, int by,
191 lcd_write_command_ex(LCD_CNTL_PAGE, by++, -1); 194 lcd_write_command_ex(LCD_CNTL_PAGE, by++, -1);
192 lcd_write_command_ex(LCD_CNTL_COLUMN, x, -1); 195 lcd_write_command_ex(LCD_CNTL_COLUMN, x, -1);
193 lcd_write_command(LCD_CNTL_DATA_WRITE); 196 lcd_write_command(LCD_CNTL_DATA_WRITE);
194 lcd_grey_data(data, width); 197 lcd_grey_data(values, phases, width);
195 data += stride; 198 values += stride;
199 phases += stride;
196 } 200 }
197} 201}
198 202
diff --git a/firmware/target/sh/archos/lcd-archos-bitmap.c b/firmware/target/sh/archos/lcd-archos-bitmap.c
index 17c4d76092..18d48f4ead 100644
--- a/firmware/target/sh/archos/lcd-archos-bitmap.c
+++ b/firmware/target/sh/archos/lcd-archos-bitmap.c
@@ -155,10 +155,13 @@ void lcd_blit(const unsigned char* data, int x, int by, int width,
155 } 155 }
156} 156}
157 157
158/* Helper function for lcd_grey_phase_blit(). */
159void lcd_grey_data(unsigned char *values, unsigned char *phases, int count);
160
158/* Performance function that works with an external buffer 161/* Performance function that works with an external buffer
159 note that by and bheight are in 8-pixel units! */ 162 note that by and bheight are in 8-pixel units! */
160void lcd_grey_phase_blit(const struct grey_data *data, int x, int by, 163void lcd_grey_phase_blit(unsigned char *values, unsigned char *phases,
161 int width, int bheight, int stride) 164 int x, int by, int width, int bheight, int stride)
162{ 165{
163 stride <<= 3; /* 8 pixels per block */ 166 stride <<= 3; /* 8 pixels per block */
164 while (bheight--) 167 while (bheight--)
@@ -167,8 +170,9 @@ void lcd_grey_phase_blit(const struct grey_data *data, int x, int by,
167 lcd_write_command (LCD_CNTL_HIGHCOL | (((x+xoffset)>>4) & 0xf)); 170 lcd_write_command (LCD_CNTL_HIGHCOL | (((x+xoffset)>>4) & 0xf));
168 lcd_write_command (LCD_CNTL_LOWCOL | ((x+xoffset) & 0xf)); 171 lcd_write_command (LCD_CNTL_LOWCOL | ((x+xoffset) & 0xf));
169 172
170 lcd_grey_data(data, width); 173 lcd_grey_data(values, phases, width);
171 data += stride; 174 values += stride;
175 phases += stride;
172 } 176 }
173} 177}
174 178
diff --git a/firmware/target/sh/archos/lcd-as-archos-bitmap.S b/firmware/target/sh/archos/lcd-as-archos-bitmap.S
index 492413fdb7..a60ea9aad1 100644
--- a/firmware/target/sh/archos/lcd-as-archos-bitmap.S
+++ b/firmware/target/sh/archos/lcd-as-archos-bitmap.S
@@ -210,28 +210,35 @@ _lcd_write_data:
210 * one or multiple pixels. 210 * one or multiple pixels.
211 * 211 *
212 * Arguments: 212 * Arguments:
213 * r4 - data address, (phase,value)-pairs 213 * r4 - pixel value data address
214 * r5 - pixel block count 214 * r5 - pixel phase data address
215 * r6 - pixel block count
215 * 216 *
216 * Register usage: 217 * Register usage:
217 * r0 - current pixel value 218 * r0 - scratch / phase signs mask
218 * r1 - scratch 219 * r1 - scratch
219 * r2 - precalculated port value (CS and SC low, DS and SD high), 220 * r2 - precalculated port value (CS and SC low, DS and SD high),
220 * negated (neg)! 221 * negated (neg)!
221 * r3 - lcd port address 222 * r3 - lcd port address
222 * r5 - end address 223 * r4 - current value address
223 * r6/r7 - current/next pixel phase 224 * r5 - current phase address
224 * r8 - current block address (for writing back phase) 225 * r6 - end address
225 * r9 - 0x80 (for phase modification) 226 * r7/r8 - current/next pixel phase
227 * r9 - current pixel value
228 * r10 - 0x00000080 \
229 * r11 - 0x00008000 > for phase sign check
230 * r12 - 0x00800000 /
226 */ 231 */
227 232
228_lcd_grey_data: 233_lcd_grey_data:
229 mov.l r8, @-r15 /* save r8 */ 234 mov.l r8, @-r15 /* save r8 */
230 shll2 r5 /* v */ 235 shll2 r6 /* v */
231 mov.l r9, @-r15 /* save r9 */ 236 mov.l r9, @-r15 /* save r9 */
232 shll2 r5 /* r5 *= 16; (8 pixel per block * 2 bytes/pixel) */ 237 shll r6 /* r6 *= 8; (8 pixels per block) */
238 mov.l r10, @-r15 /* save r10 */
239 add r4, r6 /* end address */
233 mov.l .lcdr, r3 /* put lcd data port address in r3 */ 240 mov.l .lcdr, r3 /* put lcd data port address in r3 */
234 add r4, r5 /* end address */ 241 nop /* keep alignment */
235 242
236 /* This code will fail if an interrupt changes the contents of PBDRL. 243 /* This code will fail if an interrupt changes the contents of PBDRL.
237 * If so, we must disable the interrupt here. If disabling interrupts 244 * If so, we must disable the interrupt here. If disabling interrupts
@@ -240,110 +247,90 @@ _lcd_grey_data:
240 * this would significantly decrease performance. */ 247 * this would significantly decrease performance. */
241 248
242 mov.b @r3, r0 /* r0 = PBDRL */ 249 mov.b @r3, r0 /* r0 = PBDRL */
243 mov #0x80, r9 /* for phase modification - "or #imm,xx" only allows r0 */
244 mov.b @r4+, r6 /* fetch first pixel phase */
245 or #(LCD_DS|LCD_SD), r0 /* r0 |= LCD_DS|LCD_SD */ 250 or #(LCD_DS|LCD_SD), r0 /* r0 |= LCD_DS|LCD_SD */
251 mov.l r11, @-r15 /* save r11 */
246 and #(~(LCD_CS|LCD_SC)), r0 /* r0 &= ~(LCD_CS|LCD_SC) */ 252 and #(~(LCD_CS|LCD_SC)), r0 /* r0 &= ~(LCD_CS|LCD_SC) */
253 mov.l r12, @-r15 /* save r12 */
247 neg r0, r2 /* r2 = 0 - r0 */ 254 neg r0, r2 /* r2 = 0 - r0 */
248 mov #-3, r0 /* offset for storing phase */
249 255
250 /* loop exploits that SD is on bit 0 for recorders and Ondios */ 256 /* loop exploits that SD is on bit 0 for recorders and Ondios */
251 257
252.greyloop: 258 mov.w .ptest, r10
253 cmp/pz r6 /* phase non-negative? */ 259 swap.b r10, r11
254 mov.b @r4+, r8 /* fetch pixel value */ 260 mov.l @r5, r7
255 negc r2, r1 /* T -> SD, SC low */ 261 swap.w r10, r12
256 mov.b r1, @r3 /* set port */ 262 mov.l .pmask, r0
257 or r9, r6 /* r6 -= (r6 >= 0) ? 128 : 0; */
258 mov.b @r4+, r7 /* fetch next pixel phase */
259 add #(LCD_SC), r1 /* rise SC */
260 mov.b r1, @r3 /* set port */
261 add r8, r6 /* calculate new phase */
262 mov.b r6, @(r0,r4) /* store phase */
263 263
264.greyloop:
264 cmp/pz r7 265 cmp/pz r7
265 mov.b @r4+, r8 266 mov.l @r4+, r9
266 negc r2, r1 267 negc r2, r1
267 mov.b r1, @r3 268 mov.b r1, @r3
268 or r9, r7
269 mov.b @r4+, r6
270 add #(LCD_SC), r1 269 add #(LCD_SC), r1
271 mov.b r1, @r3 270 mov.b r1, @r3
272 add r8, r7
273 mov.b r7, @(r0,r4)
274 271
275 cmp/pz r6 272 tst r12, r7
276 mov.b @r4+, r8 273 mov.l @(4,r5), r8
277 negc r2, r1 274 negc r2, r1
278 mov.b r1, @r3 275 mov.b r1, @r3
279 or r9, r6
280 mov.b @r4+, r7
281 add #(LCD_SC), r1 276 add #(LCD_SC), r1
282 mov.b r1, @r3 277 mov.b r1, @r3
283 add r8, r6
284 mov.b r6, @(r0,r4)
285 278
286 cmp/pz r7 279 tst r11, r7
287 mov.b @r4+, r8
288 negc r2, r1 280 negc r2, r1
281 tst r10, r7
289 mov.b r1, @r3 282 mov.b r1, @r3
290 or r9, r7
291 mov.b @r4+, r6
292 add #(LCD_SC), r1 283 add #(LCD_SC), r1
293 mov.b r1, @r3 284 mov.b r1, @r3
294 add r8, r7
295 mov.b r7, @(r0,r4)
296 285
297 cmp/pz r6 286 or r0, r7
298 mov.b @r4+, r8 287 sub r9, r7
299 negc r2, r1 288 negc r2, r1
300 mov.b r1, @r3 289 mov.b r1, @r3
301 or r9, r6
302 mov.b @r4+, r7
303 add #(LCD_SC), r1 290 add #(LCD_SC), r1
304 mov.b r1, @r3 291 mov.b r1, @r3
305 add r8, r6
306 mov.b r6, @(r0,r4)
307 292
308 cmp/pz r7 293 cmp/pz r8
309 mov.b @r4+, r8 294 mov.l r7, @r5
310 negc r2, r1 295 negc r2, r1
311 mov.b r1, @r3 296 mov.b r1, @r3
312 or r9, r7
313 mov.b @r4+, r6
314 add #(LCD_SC), r1 297 add #(LCD_SC), r1
315 mov.b r1, @r3 298 mov.b r1, @r3
316 add r8, r7
317 mov.b r7, @(r0,r4)
318 299
319 cmp/pz r6 300 tst r12, r8
320 mov.b @r4+, r8 301 mov.l @r4+, r9
321 negc r2, r1 302 negc r2, r1
322 mov.b r1, @r3 303 mov.b r1, @r3
323 or r9, r6
324 mov.b @r4+, r7
325 add #(LCD_SC), r1 304 add #(LCD_SC), r1
326 mov.b r1, @r3 305 mov.b r1, @r3
327 add r8, r6
328 mov.b r6, @(r0,r4)
329 306
330 cmp/pz r7 307 tst r11, r8
331 mov.b @r4+, r8 308 mov.l @(8,r5), r7
332 negc r2, r1 309 negc r2, r1
333 mov.b r1, @r3 310 mov.b r1, @r3
334 or r9, r7
335 mov.b @r4+, r6
336 add #(LCD_SC), r1 311 add #(LCD_SC), r1
337 mov.b r1, @r3 312 mov.b r1, @r3
338 add r8, r7
339 mov.b r7, @(r0,r4)
340 313
341 cmp/hi r4, r5 /* some blocks left? */ 314 tst r10, r8
315 or r0, r8
316 negc r2, r1
317 mov.b r1, @r3
318 add #(LCD_SC), r1
319 mov.b r1, @r3
320
321 sub r9, r8
322 mov.l r8, @(4,r5)
323
324 add #8, r5
325 cmp/hi r4, r6
342 bt .greyloop 326 bt .greyloop
343 327
328 mov.l @r15+, r12 /* restore r12 */
344 mov #(LCD_CS|LCD_DS|LCD_SD|LCD_SC), r0 329 mov #(LCD_CS|LCD_DS|LCD_SD|LCD_SC), r0
345 mov.l @r15+, r9 /* restore r9 */ 330 mov.l @r15+, r11 /* restore r11 */
346 or r0, r1 /* restore port */ 331 or r0, r1 /* restore port */
332 mov.l @r15+, r10 /* restore r10 */
333 mov.l @r15+, r9 /* restore r9 */
347 mov.l @r15+, r8 /* restore r8 */ 334 mov.l @r15+, r8 /* restore r8 */
348 rts 335 rts
349 mov.b r1, @r3 336 mov.b r1, @r3
@@ -351,7 +338,11 @@ _lcd_grey_data:
351 /* This is the place to reenable the interrupts, if we have disabled 338 /* This is the place to reenable the interrupts, if we have disabled
352 * them. See above. */ 339 * them. See above. */
353 340
341.ptest:
342 .short 0x0080
354 343
355 .align 2 344 .align 2
356.lcdr: 345.lcdr:
357 .long LCDR 346 .long LCDR
347.pmask:
348 .long 0x80808080