From 1102afb0b033245fe57ecef931ab19cdd7893aa9 Mon Sep 17 00:00:00 2001 From: Michael Sevakis Date: Mon, 16 Oct 2006 02:24:06 +0000 Subject: Disables hard dither mode on the x5 for routine drawing. Display driver automatically enables it when needed. Full screen frame rate up to 48 at normal CPU frequency from about 45 putting it about where it was when everything including the framebuffer was in IRAM due to the shorter and simpler lcd_write_data. Please advise if this works differently on any x5 as this might be considered a hack since nothing in the datasheet specifies using the chip this way. It is perfectly functional on mine. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11233 a1c6a512-1295-4272-9138-f99709370657 --- firmware/target/coldfire/iaudio/x5/lcd-as-x5.S | 115 +++++++++---------------- firmware/target/coldfire/iaudio/x5/lcd-x5.c | 24 +++++- 2 files changed, 64 insertions(+), 75 deletions(-) diff --git a/firmware/target/coldfire/iaudio/x5/lcd-as-x5.S b/firmware/target/coldfire/iaudio/x5/lcd-as-x5.S index 7c89fb925e..54c1110d2a 100644 --- a/firmware/target/coldfire/iaudio/x5/lcd-as-x5.S +++ b/firmware/target/coldfire/iaudio/x5/lcd-as-x5.S @@ -290,6 +290,9 @@ lcd_write_yuv420_lines: lea.l (36,%sp),%sp /* restore registers */ rts + +.yuv_end: + .size lcd_write_yuv420_lines,.yuv_end-lcd_write_yuv420_lines /* end lcd_write_yuv420_lines */ @@ -304,22 +307,19 @@ lcd_write_data: add.l %a0,%d0 /* -> end address */ lea.l 0xf0008002,%a1 /* LCD data port */ - lea.l (-24,%sp),%sp /* free up some registers */ - movem.l %d2-%d6/%a2,(%sp) + lea.l (-20,%sp),%sp /* free up some registers */ + movem.l %d2-%d5/%a2,(%sp) move.l %a0,%d1 btst.l #1,%d1 /* already longword aligned? */ beq.b .wd_wordl_end /* yes: skip initial word copy */ /* transfer initial word */ - move.w (%a0)+,%d1 /* |????????|????????|rrrrrggg|gggbbbbb| */ - move.l %d1,%d2 - and.l #0xfffff800,%d2 /* |????????|????????|rrrrr000|00000000| */ - add.l %d2,%d1 /* |????????|???????r|rrrr0ggg|gggbbbbb| */ - move.l %d1,%d2 - lsr.l #8,%d1 /* |00000000|????????|???????r|rrrr0ggg| */ - move.w %d1,(%a1) - lsl.l #1,%d2 /* |????????|??????rr|rrr0gggg|ggbbbbb0| */ - move.w %d2,(%a1) + move.w (%a0)+,%d2 /* |????????|????????|rrrrrggg|gggbbbbb| */ + move.l %d2,%d1 + lsr.l #7,%d1 /* |0000000?|????????|???????r|rrrrgggg| */ + move.w %d1,(%a1) /* ^ ^^^^^^^ */ + lsl.l #1,%d2 /* |????????|???????r|rrrrgggg|ggbbbbb0| */ + move.w %d2,(%a1) /* ^ ^^^^^^^ */ .wd_wordl_end: /* now longword aligned */ moveq.l #28,%d1 @@ -335,22 +335,17 @@ lcd_write_data: bls.b .wd_long1_end /* no: skip leading long loop */ .wd_long1_loop: - move.l (%a0)+,%d2 /* read longword */ - swap %d2 /* unstuff two pixels and correct order */ + move.l (%a0)+,%d2 /* read longword */ + swap %d2 /* |rrrrrggg|gggbbbbb|RRRRRGGG|GGGBBBBB| */ move.l %d2,%d5 - and.l #0xff00ff00,%d5 /* |rrrrrggg|00000000|rrrrrggg|00000000| */ - eor.l %d5,%d2 /* |00000000|gggbbbbb|00000000|gggbbbbb| */ - lsr.l #8,%d5 /* |00000000|rrrrrggg|00000000|rrrrrggg| */ - move.l %d5,%d6 - and.l #0x00f800f8,%d5 /* |00000000|rrrrr000|00000000|rrrrr000| */ - add.l %d6,%d5 /* |0000000r|rrrr0ggg|0000000r|rrrr0ggg| */ - move.w %d5,(%a1) - lsl.l #1,%d2 /* |0000000g|ggbbbbb0|0000000g|ggbbbbb0| */ - move.w %d2,(%a1) - swap %d5 - move.w %d5,(%a1) - swap %d2 - move.w %d2,(%a1) + lsr.l #7,%d5 /* |0000000r|rrrrgggg|ggbbbbbR|RRRRGGGG| */ + move.w %d5,(%a1) /* ^ ^^^^^^^ */ + lsl.l #1,%d2 /* |rrrrgggg|ggbbbbbR|RRRRBGGG|GGBBBBB0| */ + move.w %d2,(%a1) /* ^ ^^^^^^^ */ + swap %d5 /* |ggbbbbbR|RRRRGGGG|0000000r|rrrrgggg| */ + move.w %d5,(%a1) /* ^ ^^^^^^^ */ + swap %d2 /* |RRRRBGGG|GGBBBBB0|rrrrgggg|ggbbbbbR| */ + move.w %d2,(%a1) /* ^ ^^^^^^^ */ cmp.l %a0,%d1 bhi.b .wd_long1_loop @@ -363,15 +358,9 @@ lcd_write_data: lea.l (16,%a0),%a0 /* increment address */ /* transfer four pairs of longs to display */ - /* same procedure for each as in leading long loop */ swap %d1 move.l %d1,%d5 - and.l #0xff00ff00,%d5 - eor.l %d5,%d1 - lsr.l #8,%d5 - move.l %d5,%d6 - and.l #0x00f800f8,%d5 - add.l %d6,%d5 + lsr.l #7,%d5 move.w %d5,(%a1) lsl.l #1,%d1 move.w %d1,(%a1) @@ -380,14 +369,9 @@ lcd_write_data: swap %d1 move.w %d1,(%a1) - swap %d2 + swap %d2 move.l %d2,%d5 - and.l #0xff00ff00,%d5 - eor.l %d5,%d2 - lsr.l #8,%d5 - move.l %d5,%d6 - and.l #0x00f800f8,%d5 - add.l %d6,%d5 + lsr.l #7,%d5 move.w %d5,(%a1) lsl.l #1,%d2 move.w %d2,(%a1) @@ -396,14 +380,9 @@ lcd_write_data: swap %d2 move.w %d2,(%a1) - swap %d3 + swap %d3 move.l %d3,%d5 - and.l #0xff00ff00,%d5 - eor.l %d5,%d3 - lsr.l #8,%d5 - move.l %d5,%d6 - and.l #0x00f800f8,%d5 - add.l %d6,%d5 + lsr.l #7,%d5 move.w %d5,(%a1) lsl.l #1,%d3 move.w %d3,(%a1) @@ -412,14 +391,9 @@ lcd_write_data: swap %d3 move.w %d3,(%a1) - swap %d4 + swap %d4 move.l %d4,%d5 - and.l #0xff00ff00,%d5 - eor.l %d5,%d4 - lsr.l #8,%d5 - move.l %d5,%d6 - and.l #0x00f800f8,%d5 - add.l %d6,%d5 + lsr.l #7,%d5 move.w %d5,(%a1) lsl.l #1,%d4 move.w %d4,(%a1) @@ -437,15 +411,10 @@ lcd_write_data: bls.b .wd_long2_end /* no: skip trailing longword loop */ .wd_long2_loop: - move.l (%a0)+,%d2 /* read longword */ - swap %d2 + move.l (%a0)+,%d2 /* read longword */ + swap %d2 move.l %d2,%d5 - and.l #0xff00ff00,%d5 - eor.l %d5,%d2 - lsr.l #8,%d5 - move.l %d5,%d6 - and.l #0x00f800f8,%d5 - add.l %d6,%d5 + lsr.l #7,%d5 move.w %d5,(%a1) lsl.l #1,%d2 move.w %d2,(%a1) @@ -459,18 +428,18 @@ lcd_write_data: .wd_long2_end: blo.b .wd_word2_end /* no final word: skip */ - move.w (%a0),%d1 /* transfer final word */ - move.l %d1,%d2 - and.l #0xfffff800,%d2 - add.l %d2,%d1 - move.l %d1,%d2 - lsr.l #8,%d1 - move.w %d1,(%a1) - lsl.l #1,%d2 - move.w %d2,(%a1) + move.w (%a0)+,%d2 /* transfer final word */ + move.l %d2,%d1 + lsr.l #7,%d1 + move.w %d1,(%a1) + lsl.l #1,%d2 + move.w %d2,(%a1) .wd_word2_end: - movem.l (%sp),%d2-%d6/%a2 - lea.l (24,%sp),%sp /* restore registers */ + movem.l (%sp),%d2-%d5/%a2 + lea.l (20,%sp),%sp /* restore registers */ rts + +.wd_end: + .size lcd_write_data,.wd_end-lcd_write_data /* end lcd_write_data */ diff --git a/firmware/target/coldfire/iaudio/x5/lcd-x5.c b/firmware/target/coldfire/iaudio/x5/lcd-x5.c index c00dc74b0c..e1fac1e2ac 100755 --- a/firmware/target/coldfire/iaudio/x5/lcd-x5.c +++ b/firmware/target/coldfire/iaudio/x5/lcd-x5.c @@ -44,6 +44,9 @@ static unsigned short disp_control_rev; /* Contrast setting << 8 */ static int lcd_contrast; +/* Hardware dither bit */ +static unsigned short hw_dit = 0x0000; + /* Forward declarations */ static void lcd_display_off(void); @@ -102,6 +105,13 @@ static inline void lcd_begin_write_gram(void) LCD_CMD = R_WRITE_DATA_2_GRAM << 1; } +static void hw_dither(bool on) +{ + /* DIT=x, BGR=1, HWM=0, I/D1-0=11, AM=1, LG2-0=000 */ + hw_dit = on ? 0x8000 : 0x0000; + lcd_write_reg(R_ENTRY_MODE, 0x1038 | hw_dit); +} + /*** hardware configuration ***/ int lcd_default_contrast(void) @@ -224,8 +234,8 @@ static void lcd_power_on(void) lcd_write_reg(R_DRV_OUTPUT_CONTROL, y_offset ? 0x0013 : 0x0313); /* FLD1-0=01 (1 field), B/C=1, EOR=1 (C-pat), NW5-0=000000 (1 row) */ lcd_write_reg(R_DRV_AC_CONTROL, 0x0700); - /* DIT=1, BGR=1, HWM=0, I/D1-0=11, AM=1, LG2-0=000 */ - lcd_write_reg(R_ENTRY_MODE, 0x9038); + /* DIT=x, BGR=1, HWM=0, I/D1-0=11, AM=1, LG2-0=000 */ + lcd_write_reg(R_ENTRY_MODE, 0x1038 | hw_dit); /* CP15-0=0000000000000000 */ lcd_write_reg(R_COMPARE_REG, 0x0000); /* NO1-0=01, SDT1-0=00, EQ1-0=00, DIV1-0=00, RTN3-00000 */ @@ -379,6 +389,7 @@ void lcd_init_device(void) lcd_roll(0); lcd_set_invert_display(false); lcd_set_contrast(DEFAULT_CONTRAST_SETTING); + hw_dither(false); /* do this or all bootloaders will need reflashing */ #endif } @@ -455,6 +466,9 @@ void lcd_yuv_blit(unsigned char * const src[3], if (!display_on) return; + if (hw_dit == 0x0000) + hw_dither(true); + width = (width + 1) & ~1; height = (height + 1) & ~1; @@ -493,6 +507,9 @@ void lcd_update(void) if (!display_on) return; + if (hw_dit != 0x0000) + hw_dither(false); + /* Set start position and window */ /* Just add roll offset to start address. CP will roll back around. */ lcd_write_reg(R_RAM_ADDR_SET, y_offset + roll_offset); /* X == 0 */ @@ -513,6 +530,9 @@ void lcd_update_rect(int x, int y, int width, int height) if (!display_on) return; + if (hw_dit != 0x0000) + hw_dither(false); + if (x + width > LCD_WIDTH) width = LCD_WIDTH - x; /* Clip right */ if (x < 0) -- cgit v1.2.3