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.zip
rockbox-f3857abf6bdc9b2d570150b98c56e239ac4ebd1b.tar.gz
rockbox-f3857abf6bdc9b2d570150b98c56e239ac4ebd1b.tar.bz2
rockbox-f3857abf6bdc9b2d570150b98c56e239ac4ebd1b.tar.xz
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 d84edd6..8ee6b1c 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? */
/* called very frequently - inline! */
-inline void lcd_write_reg(int reg, int val)
+static inline void lcd_write_reg(int reg, int val)
{
*(volatile unsigned short *)0xf0000000 = reg;
*(volatile unsigned short *)0xf0000002 = val;
}
/* called very frequently - inline! */
-inline void lcd_begin_write_gram(void)
+static inline void lcd_begin_write_gram(void)
{
*(volatile unsigned short *)0xf0000000 = R_WRITE_DATA_2_GRAM;
}
-/* called very frequently - inline! */
-inline void lcd_write_data(const unsigned short* p_bytes, int count) ICODE_ATTR;
-inline void lcd_write_data(const unsigned short* p_bytes, int count)
-{
- int precount = ((-(size_t)p_bytes) & 0xf) / 2;
- count -= precount;
- while(precount--)
- *(volatile unsigned short *)0xf0000002 = *p_bytes++;
- while((count -= 8) >= 0) asm (
- "\n\tmovem.l (%[p_bytes]),%%d1-%%d4\
- \n\tswap %%d1\
- \n\tmove.w %%d1,(%[dest])\
- \n\tswap %%d1\
- \n\tmove.w %%d1,(%[dest])\
- \n\tswap %%d2\
- \n\tmove.w %%d2,(%[dest])\
- \n\tswap %%d2\
- \n\tmove.w %%d2,(%[dest])\
- \n\tswap %%d3\
- \n\tmove.w %%d3,(%[dest])\
- \n\tswap %%d3\
- \n\tmove.w %%d3,(%[dest])\
- \n\tswap %%d4\
- \n\tmove.w %%d4,(%[dest])\
- \n\tswap %%d4\
- \n\tmove.w %%d4,(%[dest])\
- \n\tlea.l (16,%[p_bytes]),%[p_bytes]"
- : [p_bytes] "+a" (p_bytes)
- : [dest] "a" ((volatile unsigned short *)0xf0000002)
- : "d1", "d2", "d3", "d4", "memory");
- if (count != 0) {
- count += 8;
- while(count--)
- *(volatile unsigned short *)0xf0000002 = *p_bytes++;
- }
-}
-
/*** hardware configuration ***/
void lcd_set_contrast(int val)
@@ -406,8 +369,8 @@ void lcd_update_rect(int x, int y, int width, int height)
lcd_write_reg(R_HORIZ_RAM_ADDR_POS, (ymax<<8) | y);
/* vert ram addr */
- lcd_write_reg(R_VERT_RAM_ADDR_POS,((x+width-1)<<8) | x);
- lcd_write_reg(R_RAM_ADDR_SET, (x<<8) | y);
+ lcd_write_reg(R_VERT_RAM_ADDR_POS,((x+width-1)<<8) | x);
+ lcd_write_reg(R_RAM_ADDR_SET, (x<<8) | y);
lcd_begin_write_gram();
/* Copy specified rectangle bitmap to hardware */
@@ -421,6 +384,6 @@ void lcd_update_rect(int x, int y, int width, int height)
lcd_write_reg(R_HORIZ_RAM_ADDR_POS, 0xaf00);
/* vert ram addr: 0 - 219 */
- lcd_write_reg(R_VERT_RAM_ADDR_POS, 0xdb00);
+ lcd_write_reg(R_VERT_RAM_ADDR_POS, 0xdb00);
}
}
diff --git a/firmware/drivers/lcd.S b/firmware/drivers/lcd.S
index 79c6e32..2b50de5 100755
--- a/firmware/drivers/lcd.S
+++ b/firmware/drivers/lcd.S
@@ -313,62 +313,135 @@ _lcd_write_data:
.type lcd_write_command,@function
lcd_write_command:
- move.l (4,%sp),%d0
- lea MBAR2,%a1
- move.l #~8,%d1
- and.l %d1,(0xb4,%a1)
- move.w %d0,0xf0000000
- rts
+ move.l (4,%sp),%d0
+ lea MBAR2,%a1
+ move.l #~8,%d1
+ and.l %d1,(0xb4,%a1)
+ move.w %d0,0xf0000000
+ rts
.align 2
.global lcd_write_command_ex
.type lcd_write_command_ex,@function
lcd_write_command_ex:
- lea MBAR2,%a1
-
- move.l (4,%sp),%d0 /* Command */
-
- move.l #~8,%d1 /* Set A0 = 0 */
- and.l %d1,(0xb4,%a1)
- move.w %d0,0xf0000000 /* Write to LCD */
-
- not.l %d1 /* Set A0 = 1 */
- or.l %d1,(0xb4,%a1)
-
- move.l (8,%sp),%d0 /* Data */
- cmp.l #0xffffffff,%d0 /* -1? */
- beq.b .last
- move.w %d0,0xf0000000 /* Write to LCD */
-
- move.l (12,%sp),%d0 /* Data */
- cmp.l #0xffffffff,%d0 /* -1? */
- beq.b .last
- move.w %d0,0xf0000000 /* Write to LCD */
-
-.last:
- rts
+ lea MBAR2,%a1
+
+ move.l (4,%sp),%d0 /* Command */
+
+ move.l #~8,%d1 /* Set A0 = 0 */
+ and.l %d1,(0xb4,%a1)
+ move.w %d0,0xf0000000 /* Write to LCD */
+
+ not.l %d1 /* Set A0 = 1 */
+ or.l %d1,(0xb4,%a1)
+
+ move.l (8,%sp),%d0 /* Data */
+ cmp.l #0xffffffff,%d0 /* -1? */
+ beq.b .last
+ move.w %d0,0xf0000000 /* Write to LCD */
+
+ move.l (12,%sp),%d0 /* Data */
+ cmp.l #0xffffffff,%d0 /* -1? */
+ beq.b .last
+ move.w %d0,0xf0000000 /* Write to LCD */
+
+.last:
+ rts
.align 2
.global lcd_write_data
.type lcd_write_data,@function
lcd_write_data:
- move.l (4,%sp),%a0 /* Data pointer */
- move.l (8,%sp),%d0 /* Length */
- lea MBAR2,%a1
- moveq #8,%d1
- or.l %d1,(0xb4,%a1)
+ move.l (4,%sp),%a0 /* Data pointer */
+ move.l (8,%sp),%d0 /* Length */
+ lea MBAR2,%a1
+ moveq #8,%d1
+ or.l %d1,(0xb4,%a1)
- lea 0xf0000000,%a1
+ lea 0xf0000000,%a1
.loop:
- /* When running in IRAM, this loop takes 7 cycles plus the LCD write.
- The 7 cycles are necessary to follow the LCD timing specs
- at 140MHz */
- move.b (%a0)+,%d1 /* 3(1/0) */
- move.w %d1,(%a1) /* 1(0/1) */
- subq.l #1,%d0 /* 1(0/0) */
- nop /* 1(0/0) */
- bne .loop /* 2(0/0) */
- rts
+ /* When running in IRAM, this loop takes 7 cycles plus the LCD write.
+ The 7 cycles are necessary to follow the LCD timing specs
+ at 140MHz */
+ move.b (%a0)+,%d1 /* 3(1/0) */
+ move.w %d1,(%a1) /* 1(0/1) */
+ subq.l #1,%d0 /* 1(0/0) */
+ nop /* 1(0/0) */
+ bne .loop /* 2(0/0) */
+ rts
+#elif defined(IRIVER_H300_SERIES)
+ .section .icode,"ax",@progbits
+
+ .align 2
+ .global lcd_write_data
+ .type lcd_write_data,@function
+
+lcd_write_data:
+ move.l (4,%sp),%a0 /* data pointer */
+ move.l (8,%sp),%d0 /* length in words */
+ add.l %d0,%d0 /* words -> bytes */
+ add.l %a0,%d0 /* -> end address */
+ lea.l 0xf0000002,%a1 /* LCD data port */
+
+ moveq.l #31,%d1
+ add.l %a0,%d1
+ and.l #0xFFFFFFF0,%d1 /* %d1 = first line bound + 16 */
+ cmp.l %d1,%d0 /* at least one full line to send? */
+ blo.b .words2_loop /* no: skip to word loop */
+
+ subq.l #8,%d1
+ subq.l #8,%d1 /* %d1 = first line bound */
+
+ cmp.l %a0,%d1 /* any leading words? */
+ bls.b .words1_end /* no: skip leading word loop */
+
+.words1_loop:
+ move.w (%a0)+,(%a1) /* transfer word */
+ cmp.l %a0,%d1 /* run %a0 up to first line bound */
+ bhi.b .words1_loop
+
+.words1_end:
+ lea.l (-16,%sp),%sp /* free up some registers */
+ movem.l %d2-%d4/%a2,(%sp)
+ move.l %d0,%a2
+ lea.l (-15,%a2),%a2 /* %a2 = end address - 15 (one line/pass) */
+
+ /* burst-optimised line transfers */
+.line_loop:
+ movem.l (%a0),%d1-%d4 /* burst-read line */
+ lea.l (16,%a0),%a0 /* increment address */
+ swap %d1 /* send data to LCD in correct order... */
+ move.w %d1,(%a1)
+ swap %d1
+ move.w %d1,(%a1)
+ swap %d2
+ move.w %d2,(%a1)
+ swap %d2
+ move.w %d2,(%a1)
+ swap %d3
+ move.w %d3,(%a1)
+ swap %d3
+ move.w %d3,(%a1)
+ swap %d4
+ move.w %d4,(%a1)
+ swap %d4
+ move.w %d4,(%a1)
+ cmp.l %a0,%a2 /* run %a0 up to last line bound */
+ bhi.b .line_loop
+
+ movem.l (%sp),%d2-%d4/%a2
+ lea.l (16,%sp),%sp /* restore registers */
+
+ cmp.l %a0,%d0 /* any trailing words? */
+ bls.b .words2_end /* no: get otta here */
+
+.words2_loop:
+ move.w (%a0)+,(%a1) /* transfer word */
+ cmp.l %a0,%d0 /* run %a0 up to end address */
+ bhi.b .words2_loop
+
+.words2_end:
+ rts
#endif