summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2006-02-05 00:24:08 +0000
committerJens Arnold <amiconn@rockbox.org>2006-02-05 00:24:08 +0000
commitf3857abf6bdc9b2d570150b98c56e239ac4ebd1b (patch)
treea9ade2bfa8c3ae3c737bf007b743b35fd1241cc6
parent1ee68b0e885c4d356111aaae919ebc94a9d7a17c (diff)
downloadrockbox-f3857abf6bdc9b2d570150b98c56e239ac4ebd1b.tar.gz
rockbox-f3857abf6bdc9b2d570150b98c56e239ac4ebd1b.zip
H300: lcd_write_data() in pure asm, essentially the same speed as before, but working correctly for all allowed data lengths. Removed RAM waste by declaring inline functions static.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8575 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/drivers/lcd-h300.c47
-rwxr-xr-xfirmware/drivers/lcd.S161
2 files changed, 122 insertions, 86 deletions
diff --git a/firmware/drivers/lcd-h300.c b/firmware/drivers/lcd-h300.c
index d84edd6b2e..8ee6b1c47e 100644
--- a/firmware/drivers/lcd-h300.c
+++ b/firmware/drivers/lcd-h300.c
@@ -77,55 +77,18 @@ static bool display_on=false; /* is the display turned on? */
77 77
78 78
79/* called very frequently - inline! */ 79/* called very frequently - inline! */
80inline void lcd_write_reg(int reg, int val) 80static inline void lcd_write_reg(int reg, int val)
81{ 81{
82 *(volatile unsigned short *)0xf0000000 = reg; 82 *(volatile unsigned short *)0xf0000000 = reg;
83 *(volatile unsigned short *)0xf0000002 = val; 83 *(volatile unsigned short *)0xf0000002 = val;
84} 84}
85 85
86/* called very frequently - inline! */ 86/* called very frequently - inline! */
87inline void lcd_begin_write_gram(void) 87static inline void lcd_begin_write_gram(void)
88{ 88{
89 *(volatile unsigned short *)0xf0000000 = R_WRITE_DATA_2_GRAM; 89 *(volatile unsigned short *)0xf0000000 = R_WRITE_DATA_2_GRAM;
90} 90}
91 91
92/* called very frequently - inline! */
93inline void lcd_write_data(const unsigned short* p_bytes, int count) ICODE_ATTR;
94inline void lcd_write_data(const unsigned short* p_bytes, int count)
95{
96 int precount = ((-(size_t)p_bytes) & 0xf) / 2;
97 count -= precount;
98 while(precount--)
99 *(volatile unsigned short *)0xf0000002 = *p_bytes++;
100 while((count -= 8) >= 0) asm (
101 "\n\tmovem.l (%[p_bytes]),%%d1-%%d4\
102 \n\tswap %%d1\
103 \n\tmove.w %%d1,(%[dest])\
104 \n\tswap %%d1\
105 \n\tmove.w %%d1,(%[dest])\
106 \n\tswap %%d2\
107 \n\tmove.w %%d2,(%[dest])\
108 \n\tswap %%d2\
109 \n\tmove.w %%d2,(%[dest])\
110 \n\tswap %%d3\
111 \n\tmove.w %%d3,(%[dest])\
112 \n\tswap %%d3\
113 \n\tmove.w %%d3,(%[dest])\
114 \n\tswap %%d4\
115 \n\tmove.w %%d4,(%[dest])\
116 \n\tswap %%d4\
117 \n\tmove.w %%d4,(%[dest])\
118 \n\tlea.l (16,%[p_bytes]),%[p_bytes]"
119 : [p_bytes] "+a" (p_bytes)
120 : [dest] "a" ((volatile unsigned short *)0xf0000002)
121 : "d1", "d2", "d3", "d4", "memory");
122 if (count != 0) {
123 count += 8;
124 while(count--)
125 *(volatile unsigned short *)0xf0000002 = *p_bytes++;
126 }
127}
128
129/*** hardware configuration ***/ 92/*** hardware configuration ***/
130 93
131void lcd_set_contrast(int val) 94void lcd_set_contrast(int val)
@@ -406,8 +369,8 @@ void lcd_update_rect(int x, int y, int width, int height)
406 lcd_write_reg(R_HORIZ_RAM_ADDR_POS, (ymax<<8) | y); 369 lcd_write_reg(R_HORIZ_RAM_ADDR_POS, (ymax<<8) | y);
407 370
408 /* vert ram addr */ 371 /* vert ram addr */
409 lcd_write_reg(R_VERT_RAM_ADDR_POS,((x+width-1)<<8) | x); 372 lcd_write_reg(R_VERT_RAM_ADDR_POS,((x+width-1)<<8) | x);
410 lcd_write_reg(R_RAM_ADDR_SET, (x<<8) | y); 373 lcd_write_reg(R_RAM_ADDR_SET, (x<<8) | y);
411 lcd_begin_write_gram(); 374 lcd_begin_write_gram();
412 375
413 /* Copy specified rectangle bitmap to hardware */ 376 /* Copy specified rectangle bitmap to hardware */
@@ -421,6 +384,6 @@ void lcd_update_rect(int x, int y, int width, int height)
421 lcd_write_reg(R_HORIZ_RAM_ADDR_POS, 0xaf00); 384 lcd_write_reg(R_HORIZ_RAM_ADDR_POS, 0xaf00);
422 385
423 /* vert ram addr: 0 - 219 */ 386 /* vert ram addr: 0 - 219 */
424 lcd_write_reg(R_VERT_RAM_ADDR_POS, 0xdb00); 387 lcd_write_reg(R_VERT_RAM_ADDR_POS, 0xdb00);
425 } 388 }
426} 389}
diff --git a/firmware/drivers/lcd.S b/firmware/drivers/lcd.S
index 79c6e32f33..2b50de5190 100755
--- a/firmware/drivers/lcd.S
+++ b/firmware/drivers/lcd.S
@@ -313,62 +313,135 @@ _lcd_write_data:
313 .type lcd_write_command,@function 313 .type lcd_write_command,@function
314 314
315lcd_write_command: 315lcd_write_command:
316 move.l (4,%sp),%d0 316 move.l (4,%sp),%d0
317 lea MBAR2,%a1 317 lea MBAR2,%a1
318 move.l #~8,%d1 318 move.l #~8,%d1
319 and.l %d1,(0xb4,%a1) 319 and.l %d1,(0xb4,%a1)
320 move.w %d0,0xf0000000 320 move.w %d0,0xf0000000
321 rts 321 rts
322 322
323 .align 2 323 .align 2
324 .global lcd_write_command_ex 324 .global lcd_write_command_ex
325 .type lcd_write_command_ex,@function 325 .type lcd_write_command_ex,@function
326 326
327lcd_write_command_ex: 327lcd_write_command_ex:
328 lea MBAR2,%a1 328 lea MBAR2,%a1
329 329
330 move.l (4,%sp),%d0 /* Command */ 330 move.l (4,%sp),%d0 /* Command */
331 331
332 move.l #~8,%d1 /* Set A0 = 0 */ 332 move.l #~8,%d1 /* Set A0 = 0 */
333 and.l %d1,(0xb4,%a1) 333 and.l %d1,(0xb4,%a1)
334 move.w %d0,0xf0000000 /* Write to LCD */ 334 move.w %d0,0xf0000000 /* Write to LCD */
335 335
336 not.l %d1 /* Set A0 = 1 */ 336 not.l %d1 /* Set A0 = 1 */
337 or.l %d1,(0xb4,%a1) 337 or.l %d1,(0xb4,%a1)
338 338
339 move.l (8,%sp),%d0 /* Data */ 339 move.l (8,%sp),%d0 /* Data */
340 cmp.l #0xffffffff,%d0 /* -1? */ 340 cmp.l #0xffffffff,%d0 /* -1? */
341 beq.b .last 341 beq.b .last
342 move.w %d0,0xf0000000 /* Write to LCD */ 342 move.w %d0,0xf0000000 /* Write to LCD */
343 343
344 move.l (12,%sp),%d0 /* Data */ 344 move.l (12,%sp),%d0 /* Data */
345 cmp.l #0xffffffff,%d0 /* -1? */ 345 cmp.l #0xffffffff,%d0 /* -1? */
346 beq.b .last 346 beq.b .last
347 move.w %d0,0xf0000000 /* Write to LCD */ 347 move.w %d0,0xf0000000 /* Write to LCD */
348 348
349.last: 349.last:
350 rts 350 rts
351 351
352 .align 2 352 .align 2
353 .global lcd_write_data 353 .global lcd_write_data
354 .type lcd_write_data,@function 354 .type lcd_write_data,@function
355 355
356lcd_write_data: 356lcd_write_data:
357 move.l (4,%sp),%a0 /* Data pointer */ 357 move.l (4,%sp),%a0 /* Data pointer */
358 move.l (8,%sp),%d0 /* Length */ 358 move.l (8,%sp),%d0 /* Length */
359 lea MBAR2,%a1 359 lea MBAR2,%a1
360 moveq #8,%d1 360 moveq #8,%d1
361 or.l %d1,(0xb4,%a1) 361 or.l %d1,(0xb4,%a1)
362 362
363 lea 0xf0000000,%a1 363 lea 0xf0000000,%a1
364.loop: 364.loop:
365 /* When running in IRAM, this loop takes 7 cycles plus the LCD write. 365 /* When running in IRAM, this loop takes 7 cycles plus the LCD write.
366 The 7 cycles are necessary to follow the LCD timing specs 366 The 7 cycles are necessary to follow the LCD timing specs
367 at 140MHz */ 367 at 140MHz */
368 move.b (%a0)+,%d1 /* 3(1/0) */ 368 move.b (%a0)+,%d1 /* 3(1/0) */
369 move.w %d1,(%a1) /* 1(0/1) */ 369 move.w %d1,(%a1) /* 1(0/1) */
370 subq.l #1,%d0 /* 1(0/0) */ 370 subq.l #1,%d0 /* 1(0/0) */
371 nop /* 1(0/0) */ 371 nop /* 1(0/0) */
372 bne .loop /* 2(0/0) */ 372 bne .loop /* 2(0/0) */
373 rts 373 rts
374#elif defined(IRIVER_H300_SERIES)
375 .section .icode,"ax",@progbits
376
377 .align 2
378 .global lcd_write_data
379 .type lcd_write_data,@function
380
381lcd_write_data:
382 move.l (4,%sp),%a0 /* data pointer */
383 move.l (8,%sp),%d0 /* length in words */
384 add.l %d0,%d0 /* words -> bytes */
385 add.l %a0,%d0 /* -> end address */
386 lea.l 0xf0000002,%a1 /* LCD data port */
387
388 moveq.l #31,%d1
389 add.l %a0,%d1
390 and.l #0xFFFFFFF0,%d1 /* %d1 = first line bound + 16 */
391 cmp.l %d1,%d0 /* at least one full line to send? */
392 blo.b .words2_loop /* no: skip to word loop */
393
394 subq.l #8,%d1
395 subq.l #8,%d1 /* %d1 = first line bound */
396
397 cmp.l %a0,%d1 /* any leading words? */
398 bls.b .words1_end /* no: skip leading word loop */
399
400.words1_loop:
401 move.w (%a0)+,(%a1) /* transfer word */
402 cmp.l %a0,%d1 /* run %a0 up to first line bound */
403 bhi.b .words1_loop
404
405.words1_end:
406 lea.l (-16,%sp),%sp /* free up some registers */
407 movem.l %d2-%d4/%a2,(%sp)
408 move.l %d0,%a2
409 lea.l (-15,%a2),%a2 /* %a2 = end address - 15 (one line/pass) */
410
411 /* burst-optimised line transfers */
412.line_loop:
413 movem.l (%a0),%d1-%d4 /* burst-read line */
414 lea.l (16,%a0),%a0 /* increment address */
415 swap %d1 /* send data to LCD in correct order... */
416 move.w %d1,(%a1)
417 swap %d1
418 move.w %d1,(%a1)
419 swap %d2
420 move.w %d2,(%a1)
421 swap %d2
422 move.w %d2,(%a1)
423 swap %d3
424 move.w %d3,(%a1)
425 swap %d3
426 move.w %d3,(%a1)
427 swap %d4
428 move.w %d4,(%a1)
429 swap %d4
430 move.w %d4,(%a1)
431 cmp.l %a0,%a2 /* run %a0 up to last line bound */
432 bhi.b .line_loop
433
434 movem.l (%sp),%d2-%d4/%a2
435 lea.l (16,%sp),%sp /* restore registers */
436
437 cmp.l %a0,%d0 /* any trailing words? */
438 bls.b .words2_end /* no: get otta here */
439
440.words2_loop:
441 move.w (%a0)+,(%a1) /* transfer word */
442 cmp.l %a0,%d0 /* run %a0 up to end address */
443 bhi.b .words2_loop
444
445.words2_end:
446 rts
374#endif 447#endif