summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2007-10-12 00:28:57 +0000
committerJens Arnold <amiconn@rockbox.org>2007-10-12 00:28:57 +0000
commit8aeed2d32e4312da426a1ba16f975923adc3cfbe (patch)
tree1a73f301a7d9bd1ea923184a8297a035557d48f7 /firmware
parente88ac4ce4a356450fafa7d06d2581ebcf425702c (diff)
downloadrockbox-8aeed2d32e4312da426a1ba16f975923adc3cfbe.tar.gz
rockbox-8aeed2d32e4312da426a1ba16f975923adc3cfbe.zip
PP LCD drivers: * Optimised and cleaned up PP colour LCD drivers. Immeasurable speedup on iPod Color, huge speedup on small H10 (a factor of 3). Should be a bit faster on big H10 too. * Big H10 changed bitmap format, so needs reconfiguring + full rebuild. * Better register naming for the mono LCD bridge. Register names for the colour LCD bridge.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15082 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/export/config-h10.h2
-rw-r--r--firmware/export/pp5002.h10
-rw-r--r--firmware/export/pp5020.h25
-rw-r--r--firmware/target/arm/ipod/lcd-color_nano.c100
-rw-r--r--firmware/target/arm/ipod/lcd-gray.c4
-rw-r--r--firmware/target/arm/iriver/h10/lcd-h10_20gb.c48
-rw-r--r--firmware/target/arm/iriver/h10/lcd-h10_5gb.c117
-rw-r--r--firmware/target/arm/sandisk/sansa-c200/lcd-c200.c8
8 files changed, 142 insertions, 172 deletions
diff --git a/firmware/export/config-h10.h b/firmware/export/config-h10.h
index 93ec226c50..8054152c77 100644
--- a/firmware/export/config-h10.h
+++ b/firmware/export/config-h10.h
@@ -39,7 +39,7 @@
39#define LCD_WIDTH 160 39#define LCD_WIDTH 160
40#define LCD_HEIGHT 128 40#define LCD_HEIGHT 128
41#define LCD_DEPTH 16 /* 65536 colours */ 41#define LCD_DEPTH 16 /* 65536 colours */
42#define LCD_PIXELFORMAT RGB565 /* rgb565 */ 42#define LCD_PIXELFORMAT RGB565SWAPPED /* rgb565 byte-swapped */
43 43
44/* Define this if your LCD can be enabled/disabled */ 44/* Define this if your LCD can be enabled/disabled */
45#define HAVE_LCD_ENABLE 45#define HAVE_LCD_ENABLE
diff --git a/firmware/export/pp5002.h b/firmware/export/pp5002.h
index c4baa7cfd3..b2e02f6174 100644
--- a/firmware/export/pp5002.h
+++ b/firmware/export/pp5002.h
@@ -23,11 +23,13 @@
23#define DRAM_START 0x28000000 23#define DRAM_START 0x28000000
24 24
25/* LCD bridge */ 25/* LCD bridge */
26#define LCD1_BASE (*(volatile unsigned long *)(0xc0001000)) 26#define LCD1_BASE 0xc0001000
27#define LCD1_CMD (*(volatile unsigned long *)(0xc0001008))
28#define LCD1_DATA (*(volatile unsigned long *)(0xc0001010))
29 27
30#define LCD1_BUSY_MASK 0x8000 28#define LCD1_CONTROL (*(volatile unsigned long *)(0xc0001000))
29#define LCD1_CMD (*(volatile unsigned long *)(0xc0001008))
30#define LCD1_DATA (*(volatile unsigned long *)(0xc0001010))
31
32#define LCD1_BUSY_MASK 0x8000
31 33
32/* I2S controller */ 34/* I2S controller */
33#define IISCONFIG (*(volatile unsigned long *)(0xc0002500)) 35#define IISCONFIG (*(volatile unsigned long *)(0xc0002500))
diff --git a/firmware/export/pp5020.h b/firmware/export/pp5020.h
index 2c939300ab..5654a7de63 100644
--- a/firmware/export/pp5020.h
+++ b/firmware/export/pp5020.h
@@ -407,16 +407,33 @@
407/* Note: didn't bother to see of levels 0 and 16 actually work */ 407/* Note: didn't bother to see of levels 0 and 16 actually work */
408 408
409/* First ("mono") LCD bridge */ 409/* First ("mono") LCD bridge */
410#define LCD1_BASE (*(volatile unsigned long *)(0x70003000)) 410#define LCD1_BASE 0x70003000
411#define LCD1_CMD (*(volatile unsigned long *)(0x70003008))
412#define LCD1_DATA (*(volatile unsigned long *)(0x70003010))
413 411
414#define LCD1_BUSY_MASK 0x8000 412#define LCD1_CONTROL (*(volatile unsigned long *)(0x70003000))
413#define LCD1_CMD (*(volatile unsigned long *)(0x70003008))
414#define LCD1_DATA (*(volatile unsigned long *)(0x70003010))
415
416#define LCD1_BUSY_MASK 0x8000
415 417
416/* Serial Controller */ 418/* Serial Controller */
417#define SERIAL0 (*(volatile unsigned long*)(0x70006000)) 419#define SERIAL0 (*(volatile unsigned long*)(0x70006000))
418#define SERIAL1 (*(volatile unsigned long*)(0x70006040)) 420#define SERIAL1 (*(volatile unsigned long*)(0x70006040))
419 421
422/* Second ("color") LCD bridge */
423#define LCD2_BASE 0x70008a00
424
425#define LCD2_PORT (*(volatile unsigned long*)(0x70008a0c))
426#define LCD2_BLOCK_CTRL (*(volatile unsigned long*)(0x70008a20))
427#define LCD2_BLOCK_CONFIG (*(volatile unsigned long*)(0x70008a24))
428#define LCD2_BLOCK_DATA (*(volatile unsigned long*)(0x70008b00))
429
430#define LCD2_BUSY_MASK 0x80000000
431#define LCD2_CMD_MASK 0x80000000
432#define LCD2_DATA_MASK 0x81000000
433
434#define LCD2_BLOCK_READY 0x04000000
435#define LCD2_BLOCK_TXOK 0x01000000
436
420/* I2C */ 437/* I2C */
421#define I2C_BASE 0x7000c000 438#define I2C_BASE 0x7000c000
422 439
diff --git a/firmware/target/arm/ipod/lcd-color_nano.c b/firmware/target/arm/ipod/lcd-color_nano.c
index c17b99b859..f3a5819d6b 100644
--- a/firmware/target/arm/ipod/lcd-color_nano.c
+++ b/firmware/target/arm/ipod/lcd-color_nano.c
@@ -30,15 +30,6 @@
30#include "system.h" 30#include "system.h"
31#include "hwcompat.h" 31#include "hwcompat.h"
32 32
33/* check if number of useconds has past */
34static inline bool timer_check(int clock_start, int usecs)
35{
36 return ((int)(USEC_TIMER - clock_start)) >= usecs;
37}
38
39#define IPOD_LCD_BASE 0x70008a0c
40#define IPOD_LCD_BUSY_MASK 0x80000000
41
42/* LCD command codes for HD66789R */ 33/* LCD command codes for HD66789R */
43#define LCD_CNTL_RAM_ADDR_SET 0x21 34#define LCD_CNTL_RAM_ADDR_SET 0x21
44#define LCD_CNTL_WRITE_TO_GRAM 0x22 35#define LCD_CNTL_WRITE_TO_GRAM 0x22
@@ -48,39 +39,25 @@ static inline bool timer_check(int clock_start, int usecs)
48/*** globals ***/ 39/*** globals ***/
49int lcd_type = 1; /* 0 = "old" Color/Photo, 1 = "new" Color & Nano */ 40int lcd_type = 1; /* 0 = "old" Color/Photo, 1 = "new" Color & Nano */
50 41
51static void lcd_wait_write(void) 42static inline void lcd_wait_write(void)
52{
53 if ((inl(IPOD_LCD_BASE) & IPOD_LCD_BUSY_MASK) != 0) {
54 int start = USEC_TIMER;
55
56 do {
57 if ((inl(IPOD_LCD_BASE) & IPOD_LCD_BUSY_MASK) == 0) break;
58 } while (timer_check(start, 1000) == 0);
59 }
60}
61
62static void lcd_send_lo(int v)
63{
64 lcd_wait_write();
65 outl(v | 0x80000000, IPOD_LCD_BASE);
66}
67
68static void lcd_send_hi(int v)
69{ 43{
70 lcd_wait_write(); 44 while (LCD2_PORT & LCD2_BUSY_MASK);
71 outl(v | 0x81000000, IPOD_LCD_BASE);
72} 45}
73 46
74static void lcd_cmd_data(int cmd, int data) 47static void lcd_cmd_data(unsigned cmd, unsigned data)
75{ 48{
76 if (lcd_type == 0) { 49 if (lcd_type == 0) { /* 16 bit transfers */
77 lcd_send_lo(cmd); 50 lcd_wait_write();
78 lcd_send_lo(data); 51 LCD2_PORT = LCD2_CMD_MASK | cmd;
52 lcd_wait_write();
53 LCD2_PORT = LCD2_CMD_MASK | data;
79 } else { 54 } else {
80 lcd_send_lo(0x0); 55 lcd_wait_write();
81 lcd_send_lo(cmd); 56 LCD2_PORT = LCD2_CMD_MASK;
82 lcd_send_hi((data >> 8) & 0xff); 57 LCD2_PORT = LCD2_CMD_MASK | cmd;
83 lcd_send_hi(data & 0xff); 58 lcd_wait_write();
59 LCD2_PORT = LCD2_DATA_MASK | (data >> 8);
60 LCD2_PORT = LCD2_DATA_MASK | (data & 0xff);
84 } 61 }
85} 62}
86 63
@@ -229,8 +206,9 @@ void lcd_yuv_blit(unsigned char * const src[3],
229 lcd_cmd_data(LCD_CNTL_RAM_ADDR_SET, ((x0 << 8) | y0)); 206 lcd_cmd_data(LCD_CNTL_RAM_ADDR_SET, ((x0 << 8) | y0));
230 207
231 /* start drawing */ 208 /* start drawing */
232 lcd_send_lo(0x0); 209 lcd_wait_write();
233 lcd_send_lo(LCD_CNTL_WRITE_TO_GRAM); 210 LCD2_PORT = LCD2_CMD_MASK;
211 LCD2_PORT = (LCD2_CMD_MASK|LCD_CNTL_WRITE_TO_GRAM);
234 } 212 }
235 213
236 const int stride_div_csub_x = stride/CSUB_X; 214 const int stride_div_csub_x = stride/CSUB_X;
@@ -257,8 +235,8 @@ void lcd_yuv_blit(unsigned char * const src[3],
257 fb_data pixel1,pixel2; 235 fb_data pixel1,pixel2;
258 236
259 if (h==0) { 237 if (h==0) {
260 while ((inl(0x70008a20) & 0x4000000) == 0); 238 while (!(LCD2_BLOCK_CTRL & LCD2_BLOCK_READY));
261 outl(0x0, 0x70008a24); 239 LCD2_BLOCK_CONFIG = 0;
262 240
263 if (height == 0) break; 241 if (height == 0) break;
264 242
@@ -272,9 +250,9 @@ void lcd_yuv_blit(unsigned char * const src[3],
272 } 250 }
273 251
274 height -= h; 252 height -= h;
275 outl(0x10000080, 0x70008a20); 253 LCD2_BLOCK_CTRL = 0x10000080;
276 outl((pixels_to_write - 1) | 0xc0010000, 0x70008a24); 254 LCD2_BLOCK_CONFIG = 0xc0010000 | (pixels_to_write - 1);
277 outl(0x34000000, 0x70008a20); 255 LCD2_BLOCK_CTRL = 0x34000000;
278 } 256 }
279 257
280 do 258 do
@@ -368,10 +346,10 @@ void lcd_yuv_blit(unsigned char * const src[3],
368 bbits = blue2 >> 16 ; 346 bbits = blue2 >> 16 ;
369 pixel2 = swap16((rbits << 11) | (gbits << 5) | bbits); 347 pixel2 = swap16((rbits << 11) | (gbits << 5) | bbits);
370 348
371 while ((inl(0x70008a20) & 0x1000000) == 0); 349 while (!(LCD2_BLOCK_CTRL & LCD2_BLOCK_TXOK));
372 350
373 /* output 2 pixels */ 351 /* output 2 pixels */
374 outl((pixel2<<16)|pixel1, 0x70008b00); 352 LCD2_BLOCK_DATA = (pixel2 << 16) | pixel1;
375 } 353 }
376 while (ysrc < row_end); 354 while (ysrc < row_end);
377 355
@@ -379,8 +357,8 @@ void lcd_yuv_blit(unsigned char * const src[3],
379 h--; 357 h--;
380 } 358 }
381 359
382 while ((inl(0x70008a20) & 0x4000000) == 0); 360 while (!(LCD2_BLOCK_CTRL & LCD2_BLOCK_READY));
383 outl(0x0, 0x70008a24); 361 LCD2_BLOCK_CONFIG = 0;
384} 362}
385 363
386 364
@@ -389,8 +367,7 @@ void lcd_update_rect(int x, int y, int width, int height)
389{ 367{
390 int y0, x0, y1, x1; 368 int y0, x0, y1, x1;
391 int newx,newwidth; 369 int newx,newwidth;
392 370 unsigned long *addr;
393 unsigned long *addr = (unsigned long *)lcd_framebuffer;
394 371
395 /* Ensure x and width are both even - so we can read 32-bit aligned 372 /* Ensure x and width are both even - so we can read 32-bit aligned
396 data from lcd_framebuffer */ 373 data from lcd_framebuffer */
@@ -449,8 +426,9 @@ void lcd_update_rect(int x, int y, int width, int height)
449 lcd_cmd_data(LCD_CNTL_RAM_ADDR_SET, ((x0 << 8) | y0)); 426 lcd_cmd_data(LCD_CNTL_RAM_ADDR_SET, ((x0 << 8) | y0));
450 427
451 /* start drawing */ 428 /* start drawing */
452 lcd_send_lo(0x0); 429 lcd_wait_write();
453 lcd_send_lo(LCD_CNTL_WRITE_TO_GRAM); 430 LCD2_PORT = LCD2_CMD_MASK;
431 LCD2_PORT = (LCD2_CMD_MASK|LCD_CNTL_WRITE_TO_GRAM);
454 } 432 }
455 433
456 addr = (unsigned long*)&lcd_framebuffer[y][x]; 434 addr = (unsigned long*)&lcd_framebuffer[y][x];
@@ -468,28 +446,26 @@ void lcd_update_rect(int x, int y, int width, int height)
468 pixels_to_write = (width * h) * 2; 446 pixels_to_write = (width * h) * 2;
469 } 447 }
470 448
471 outl(0x10000080, 0x70008a20); 449 LCD2_BLOCK_CTRL = 0x10000080;
472 outl((pixels_to_write - 1) | 0xc0010000, 0x70008a24); 450 LCD2_BLOCK_CONFIG = 0xc0010000 | (pixels_to_write - 1);
473 outl(0x34000000, 0x70008a20); 451 LCD2_BLOCK_CTRL = 0x34000000;
474 452
475 /* for each row */ 453 /* for each row */
476 for (r = 0; r < h; r++) { 454 for (r = 0; r < h; r++) {
477 /* for each column */ 455 /* for each column */
478 for (c = 0; c < width; c += 2) { 456 for (c = 0; c < width; c += 2) {
479 while ((inl(0x70008a20) & 0x1000000) == 0); 457 while (!(LCD2_BLOCK_CTRL & LCD2_BLOCK_TXOK));
480 458
481 /* output 2 pixels */ 459 /* output 2 pixels */
482 outl(*(addr++), 0x70008b00); 460 LCD2_BLOCK_DATA = *addr++;
483 } 461 }
484
485 addr += (LCD_WIDTH - width)/2; 462 addr += (LCD_WIDTH - width)/2;
486 } 463 }
487 464
488 while ((inl(0x70008a20) & 0x4000000) == 0); 465 while (!(LCD2_BLOCK_CTRL & LCD2_BLOCK_READY));
489 466 LCD2_BLOCK_CONFIG = 0;
490 outl(0x0, 0x70008a24);
491 467
492 height = height - h; 468 height -= h;
493 } 469 }
494} 470}
495 471
diff --git a/firmware/target/arm/ipod/lcd-gray.c b/firmware/target/arm/ipod/lcd-gray.c
index bea1ed46ed..c375d95ea6 100644
--- a/firmware/target/arm/ipod/lcd-gray.c
+++ b/firmware/target/arm/ipod/lcd-gray.c
@@ -84,7 +84,7 @@ static const unsigned char dibits[16] ICONST_ATTR = {
84/* wait for LCD with timeout */ 84/* wait for LCD with timeout */
85static inline void lcd_wait_write(void) 85static inline void lcd_wait_write(void)
86{ 86{
87 while (LCD1_BASE & LCD1_BUSY_MASK); 87 while (LCD1_CONTROL & LCD1_BUSY_MASK);
88} 88}
89 89
90/* send LCD data */ 90/* send LCD data */
@@ -155,7 +155,7 @@ void lcd_init_device(void)
155 power_reg_h = 0x1100; 155 power_reg_h = 0x1100;
156#elif defined IPOD_MINI2G 156#elif defined IPOD_MINI2G
157 lcd_wait_write(); 157 lcd_wait_write();
158 LCD1_BASE = (LCD1_BASE & ~0x1f00000) | 0x1700000; 158 LCD1_CONTROL = (LCD1_CONTROL & ~0x1f00000) | 0x1700000;
159#endif 159#endif
160 160
161 lcd_cmd_and_data(R_POWER_CONTROL, POWER_REG_H | 0xc); 161 lcd_cmd_and_data(R_POWER_CONTROL, POWER_REG_H | 0xc);
diff --git a/firmware/target/arm/iriver/h10/lcd-h10_20gb.c b/firmware/target/arm/iriver/h10/lcd-h10_20gb.c
index f6ea87c1d0..a52e98f364 100644
--- a/firmware/target/arm/iriver/h10/lcd-h10_20gb.c
+++ b/firmware/target/arm/iriver/h10/lcd-h10_20gb.c
@@ -22,12 +22,6 @@
22#include "kernel.h" 22#include "kernel.h"
23#include "system.h" 23#include "system.h"
24 24
25/* check if number of useconds has past */
26static inline bool timer_check(int clock_start, int usecs)
27{
28 return ((int)(USEC_TIMER - clock_start)) >= usecs;
29}
30
31/** Initialized in lcd_init_device() **/ 25/** Initialized in lcd_init_device() **/
32/* Is the power turned on? */ 26/* Is the power turned on? */
33static bool power_on; 27static bool power_on;
@@ -43,17 +37,6 @@ static int lcd_contrast;
43/* Forward declarations */ 37/* Forward declarations */
44static void lcd_display_off(void); 38static void lcd_display_off(void);
45 39
46/* Hardware address of LCD. Bits are:
47 * 31 - set to write, poll for completion.
48 * 24 - 0 for command, 1 for data
49 * 7..0 - command/data to send
50 * Commands/Data are always sent in 16-bits, msb first.
51 */
52#define LCD_BASE *(volatile unsigned int *)0x70008a0c
53#define LCD_BUSY_MASK 0x80000000
54#define LCD_CMD 0x80000000
55#define LCD_DATA 0x81000000
56
57/* register defines for the Renesas HD66773R */ 40/* register defines for the Renesas HD66773R */
58#define R_START_OSC 0x00 41#define R_START_OSC 0x00
59#define R_DEVICE_CODE_READ 0x00 42#define R_DEVICE_CODE_READ 0x00
@@ -91,31 +74,34 @@ static void lcd_display_off(void);
91 74
92static inline void lcd_wait_write(void) 75static inline void lcd_wait_write(void)
93{ 76{
94 if ((LCD_BASE & LCD_BUSY_MASK) != 0) { 77 while (LCD2_PORT & LCD2_BUSY_MASK);
95 int start = USEC_TIMER;
96
97 do {
98 if ((LCD_BASE & LCD_BUSY_MASK) == 0) break;
99 } while (timer_check(start, 1000) == 0);
100 }
101} 78}
102 79
103/* Send command */ 80/* Send command */
104static inline void lcd_send_cmd(int v) 81static inline void lcd_send_cmd(unsigned v)
105{ 82{
106 lcd_wait_write(); 83 lcd_wait_write();
107 LCD_BASE = 0x00000000 | LCD_CMD; 84 LCD2_PORT = LCD2_CMD_MASK;
108 LCD_BASE = v | LCD_CMD; 85 LCD2_PORT = LCD2_CMD_MASK | v;
109} 86}
110 87
111/* Send 16-bit data */ 88/* Send 16-bit data */
112static inline void lcd_send_data(int v) 89static inline void lcd_send_data(unsigned v)
113{ 90{
114 lcd_wait_write(); 91 lcd_wait_write();
115 LCD_BASE = ((v>>8) & 0xff) | LCD_DATA; /* Send MSB first */ 92 LCD2_PORT = LCD2_DATA_MASK | (v >> 8); /* Send MSB first */
116 LCD_BASE = ( v & 0xff) | LCD_DATA; 93 LCD2_PORT = LCD2_DATA_MASK | (v & 0xff);
117} 94}
118 95
96/* Send 16-bit data byte-swapped. Only needed until we can use block transfer. */
97static inline void lcd_send_data_swapped(unsigned v)
98{
99 lcd_wait_write();
100 LCD2_PORT = LCD2_DATA_MASK | (v & 0xff); /* Send LSB first */
101 LCD2_PORT = LCD2_DATA_MASK | (v >> 8);
102}
103
104
119/* Write value to register */ 105/* Write value to register */
120static inline void lcd_write_reg(int reg, int val) 106static inline void lcd_write_reg(int reg, int val)
121{ 107{
@@ -635,7 +621,7 @@ void lcd_update_rect(int x0, int y0, int width, int height)
635 /* for each column */ 621 /* for each column */
636 for (c = 0; c < width; c++) { 622 for (c = 0; c < width; c++) {
637 /* output 1 pixel */ 623 /* output 1 pixel */
638 lcd_send_data(*(addr++)); 624 lcd_send_data_swapped(*addr++);
639 } 625 }
640 626
641 addr += LCD_WIDTH - width; 627 addr += LCD_WIDTH - width;
diff --git a/firmware/target/arm/iriver/h10/lcd-h10_5gb.c b/firmware/target/arm/iriver/h10/lcd-h10_5gb.c
index c1f447a80c..7555c566f0 100644
--- a/firmware/target/arm/iriver/h10/lcd-h10_5gb.c
+++ b/firmware/target/arm/iriver/h10/lcd-h10_5gb.c
@@ -22,23 +22,6 @@
22#include "kernel.h" 22#include "kernel.h"
23#include "system.h" 23#include "system.h"
24 24
25/* check if number of useconds has past */
26static inline bool timer_check(int clock_start, int usecs)
27{
28 return ((int)(USEC_TIMER - clock_start)) >= usecs;
29}
30
31/* Hardware address of LCD. Bits are:
32 * 31 - set to write, poll for completion.
33 * 24 - 0 for command, 1 for data
34 * 7..0 - command/data to send
35 * Commands/Data are always sent in 16-bits, msb first.
36 */
37#define LCD_BASE *(volatile unsigned int *)0x70008a0c
38#define LCD_BUSY_MASK 0x80000000
39#define LCD_CMD 0x80000000
40#define LCD_DATA 0x81000000
41
42/* register defines for TL1771 */ 25/* register defines for TL1771 */
43#define R_START_OSC 0x00 26#define R_START_OSC 0x00
44#define R_DEVICE_CODE_READ 0x00 27#define R_DEVICE_CODE_READ 0x00
@@ -72,38 +55,23 @@ static inline bool timer_check(int clock_start, int usecs)
72 55
73static inline void lcd_wait_write(void) 56static inline void lcd_wait_write(void)
74{ 57{
75 if ((LCD_BASE & LCD_BUSY_MASK) != 0) { 58 while (LCD2_PORT & LCD2_BUSY_MASK);
76 int start = USEC_TIMER;
77
78 do {
79 if ((LCD_BASE & LCD_BUSY_MASK) == 0) break;
80 } while (timer_check(start, 1000) == 0);
81 }
82} 59}
83 60
84/* Send command */ 61/* Send command */
85static inline void lcd_send_cmd(int v) 62static inline void lcd_send_cmd(unsigned v)
86{ 63{
87 lcd_wait_write(); 64 lcd_wait_write();
88 LCD_BASE = 0x00000000 | LCD_CMD; 65 LCD2_PORT = LCD2_CMD_MASK;
89 LCD_BASE = v | LCD_CMD; 66 LCD2_PORT = LCD2_CMD_MASK | v;
90} 67}
91 68
92/* Send 16-bit data */ 69/* Send 16-bit data */
93static inline void lcd_send_data(int v) 70static inline void lcd_send_data(unsigned v)
94{ 71{
95 lcd_wait_write(); 72 lcd_wait_write();
96 LCD_BASE = ( v & 0xff) | LCD_DATA; /* Send MSB first */ 73 LCD2_PORT = LCD2_DATA_MASK | (v >> 8); /* Send MSB first */
97 LCD_BASE = ((v>>8) & 0xff) | LCD_DATA; 74 LCD2_PORT = LCD2_DATA_MASK | (v & 0xff);
98}
99
100/* Send two 16-bit data */
101static inline void lcd_send_data2(int v)
102{
103 unsigned int vsr = v;
104 lcd_send_data(vsr);
105 vsr = v >> 16;
106 lcd_send_data(vsr);
107} 75}
108 76
109 77
@@ -181,17 +149,17 @@ void lcd_yuv_blit(unsigned char * const src[3],
181 y0 = y; 149 y0 = y;
182 y1 = y + height - 1; 150 y1 = y + height - 1;
183 151
184 /* start horiz << 8 | max horiz */ 152 /* max horiz << 8 | start horiz */
185 lcd_send_cmd(R_HORIZ_RAM_ADDR_POS); 153 lcd_send_cmd(R_HORIZ_RAM_ADDR_POS);
186 lcd_send_data((x0 << 8) | x1); 154 lcd_send_data((x1 << 8) | x0);
187 155
188 /* start vert << 8 | max vert */ 156 /* max vert << 8 | start vert */
189 lcd_send_cmd(R_VERT_RAM_ADDR_POS); 157 lcd_send_cmd(R_VERT_RAM_ADDR_POS);
190 lcd_send_data((y0 << 8) | y1); 158 lcd_send_data((y1 << 8) | y0);
191 159
192 /* start horiz << 8 | start vert */ 160 /* start vert << 8 | start horiz */
193 lcd_send_cmd(R_RAM_ADDR_SET); 161 lcd_send_cmd(R_RAM_ADDR_SET);
194 lcd_send_data(((x0 << 8) | y0)); 162 lcd_send_data((y0 << 8) | x0);
195 163
196 /* start drawing */ 164 /* start drawing */
197 lcd_send_cmd(R_WRITE_DATA_2_GRAM); 165 lcd_send_cmd(R_WRITE_DATA_2_GRAM);
@@ -302,12 +270,12 @@ void lcd_yuv_blit(unsigned char * const src[3],
302 rbits = red1 >> 16 ; 270 rbits = red1 >> 16 ;
303 gbits = green1 >> 15 ; 271 gbits = green1 >> 15 ;
304 bbits = blue1 >> 16 ; 272 bbits = blue1 >> 16 ;
305 lcd_send_data(swap16((rbits << 11) | (gbits << 5) | bbits)); 273 lcd_send_data((rbits << 11) | (gbits << 5) | bbits);
306 274
307 rbits = red2 >> 16 ; 275 rbits = red2 >> 16 ;
308 gbits = green2 >> 15 ; 276 gbits = green2 >> 15 ;
309 bbits = blue2 >> 16 ; 277 bbits = blue2 >> 16 ;
310 lcd_send_data(swap16((rbits << 11) | (gbits << 5) | bbits)); 278 lcd_send_data((rbits << 11) | (gbits << 5) | bbits);
311 } 279 }
312 while (ysrc < row_end); 280 while (ysrc < row_end);
313 281
@@ -321,8 +289,7 @@ void lcd_update_rect(int x0, int y0, int width, int height)
321{ 289{
322 int x1, y1; 290 int x1, y1;
323 int newx,newwidth; 291 int newx,newwidth;
324 292 unsigned long *addr;
325 unsigned long *addr = (unsigned long *)lcd_framebuffer;
326 293
327 /* Ensure x and width are both even - so we can read 32-bit aligned 294 /* Ensure x and width are both even - so we can read 32-bit aligned
328 data from lcd_framebuffer */ 295 data from lcd_framebuffer */
@@ -352,34 +319,56 @@ void lcd_update_rect(int x0, int y0, int width, int height)
352 x1 = t; 319 x1 = t;
353 } 320 }
354 321
355 /* start horiz << 8 | max horiz */ 322 /* max horiz << 8 | start horiz */
356 lcd_send_cmd(R_HORIZ_RAM_ADDR_POS); 323 lcd_send_cmd(R_HORIZ_RAM_ADDR_POS);
357 lcd_send_data((x0 << 8) | x1); 324 lcd_send_data((x1 << 8) | x0);
358 325
359 /* start vert << 8 | max vert */ 326 /* max vert << 8 | start vert */
360 lcd_send_cmd(R_VERT_RAM_ADDR_POS); 327 lcd_send_cmd(R_VERT_RAM_ADDR_POS);
361 lcd_send_data((y0 << 8) | y1); 328 lcd_send_data((y1 << 8) | y0);
362 329
363 /* start horiz << 8 | start vert */ 330 /* start vert << 8 | start horiz */
364 lcd_send_cmd(R_RAM_ADDR_SET); 331 lcd_send_cmd(R_RAM_ADDR_SET);
365 lcd_send_data(((x0 << 8) | y0)); 332 lcd_send_data((y0 << 8) | x0);
366 333
367 /* start drawing */ 334 /* start drawing */
368 lcd_send_cmd(R_WRITE_DATA_2_GRAM); 335 lcd_send_cmd(R_WRITE_DATA_2_GRAM);
369 336
370 addr = (unsigned long*)&lcd_framebuffer[y0][x0]; 337 addr = (unsigned long*)&lcd_framebuffer[y0][x0];
371 338
372 int c, r; 339 while (height > 0) {
340 int c, r;
341 int h, pixels_to_write;
342
343 pixels_to_write = (width * height) * 2;
344 h = height;
373 345
374 /* for each row */ 346 /* calculate how much we can do in one go */
375 for (r = 0; r < height; r++) { 347 if (pixels_to_write > 0x10000) {
376 /* for each column */ 348 h = (0x10000/2) / width;
377 for (c = 0; c < width; c += 2) { 349 pixels_to_write = (width * h) * 2;
378 /* output 2 pixels */
379 lcd_send_data2(*(addr++));
380 } 350 }
381 351
382 addr += (LCD_WIDTH - width)/2; 352 LCD2_BLOCK_CTRL = 0x10000080;
353 LCD2_BLOCK_CONFIG = 0xc0010000 | (pixels_to_write - 1);
354 LCD2_BLOCK_CTRL = 0x34000000;
355
356 /* for each row */
357 for (r = 0; r < h; r++) {
358 /* for each column */
359 for (c = 0; c < width; c += 2) {
360 while (!(LCD2_BLOCK_CTRL & LCD2_BLOCK_TXOK));
361
362 /* output 2 pixels */
363 LCD2_BLOCK_DATA = *addr++;
364 }
365 addr += (LCD_WIDTH - width)/2;
366 }
367
368 while (!(LCD2_BLOCK_CTRL & LCD2_BLOCK_READY));
369 LCD2_BLOCK_CONFIG = 0;
370
371 height -= h;
383 } 372 }
384} 373}
385 374
diff --git a/firmware/target/arm/sandisk/sansa-c200/lcd-c200.c b/firmware/target/arm/sandisk/sansa-c200/lcd-c200.c
index d503fd2c9b..24a7585508 100644
--- a/firmware/target/arm/sandisk/sansa-c200/lcd-c200.c
+++ b/firmware/target/arm/sandisk/sansa-c200/lcd-c200.c
@@ -62,7 +62,7 @@
62/* wait for LCD */ 62/* wait for LCD */
63static inline void lcd_wait_write(void) 63static inline void lcd_wait_write(void)
64{ 64{
65 while (LCD1_BASE & LCD1_BUSY_MASK); 65 while (LCD1_CONTROL & LCD1_BUSY_MASK);
66} 66}
67 67
68/* send LCD data */ 68/* send LCD data */
@@ -91,13 +91,13 @@ void lcd_init_device(void)
91 DEV_INIT &= ~0x400; 91 DEV_INIT &= ~0x400;
92 udelay(10000); 92 udelay(10000);
93 93
94 LCD1_BASE &= ~0x4; 94 LCD1_CONTROL &= ~0x4;
95 udelay(15); 95 udelay(15);
96 96
97 LCD1_BASE |= 0x4; 97 LCD1_CONTROL |= 0x4;
98 udelay(10); 98 udelay(10);
99 99
100 LCD1_BASE = 0x4687; 100 LCD1_CONTROL = 0x4687;
101 udelay(10000); 101 udelay(10000);
102 102
103 lcd_send_command(R_STANDBY_OFF); 103 lcd_send_command(R_STANDBY_OFF);