From 8ac46f844f437a31f72d73a41a6d3852d8b96143 Mon Sep 17 00:00:00 2001 From: James Buren Date: Thu, 12 Nov 2020 14:02:23 +0000 Subject: [PATCH] h300: fix one long-standing bootloader bug This was introduced in e13c6001332882291363bdf2f1155875439fe187 back when the author was trying to optimize the LCD code with DMA. For whatever reason this broke the bootloader for the last 10 years or so and no one could figure out why. This is now fixed. However the bootloader is still currently broken in HEAD due to recent changes to the LCD code. A fix for that is not yet known. Change-Id: I046d53f9f391f558c391f2fadb6b260fe3be4d92 --- .../target/coldfire/iriver/h300/lcd-h300.c | 58 ++++++++++++++++++- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/firmware/target/coldfire/iriver/h300/lcd-h300.c b/firmware/target/coldfire/iriver/h300/lcd-h300.c index 312bd70ccc..c415ed6c37 100644 --- a/firmware/target/coldfire/iriver/h300/lcd-h300.c +++ b/firmware/target/coldfire/iriver/h300/lcd-h300.c @@ -35,11 +35,13 @@ static bool display_on = false; /* Is the display turned on? */ static bool display_flipped = false; static int xoffset = 0; /* Needed for flip */ +#ifndef BOOTLOADER static struct mutex lcd_mtx; /* The update functions use DMA and yield */ unsigned long dma_addr IBSS_ATTR; unsigned int dma_len IBSS_ATTR; volatile int dma_count IBSS_ATTR; +#endif /* register defines */ #define R_START_OSC 0x00 @@ -139,9 +141,13 @@ void lcd_set_flip(bool yesno) if (display_on) { +#ifndef BOOTLOADER mutex_lock(&lcd_mtx); +#endif flip_lcd(yesno); +#ifndef BOOTLOADER mutex_unlock(&lcd_mtx); +#endif } } @@ -262,6 +268,7 @@ void lcd_init_device(void) or_l(0x00004000, &GPIO1_OUT); sleep(1); +#ifndef BOOTLOADER DAR3 = 0xf0000002; /* Configure DMA channel 3 */ DSR3 = 1; DIVR3 = 57; /* DMA3 is mapped into vector 57 in system.c */ @@ -269,6 +276,7 @@ void lcd_init_device(void) coldfire_imr_mod(0, 1 << 17); mutex_init(&lcd_mtx); +#endif _display_on(); } @@ -276,7 +284,9 @@ void lcd_enable(bool on) { if (display_on != on) { +#ifndef BOOTLOADER mutex_lock(&lcd_mtx); +#endif if (on) { _display_on(); @@ -304,7 +314,9 @@ void lcd_enable(bool on) display_on=false; } +#ifndef BOOTLOADER mutex_unlock(&lcd_mtx); +#endif } } @@ -340,7 +352,9 @@ void lcd_blit_yuv(unsigned char * const src[3], if (!display_on) return; +#ifndef BOOTLOADER mutex_lock(&lcd_mtx); +#endif width &= ~1; /* stay on the safe side */ height &= ~1; @@ -372,9 +386,12 @@ void lcd_blit_yuv(unsigned char * const src[3], vsrc += stride >> 1; } while (ysrc < ysrc_max); +#ifndef BOOTLOADER mutex_unlock(&lcd_mtx); +#endif } +#ifndef BOOTLOADER /* LCD DMA ISR */ void DMA3(void) __attribute__ ((interrupt_handler, section(".icode"))); void DMA3(void) @@ -390,6 +407,7 @@ void DMA3(void) | DMA_DSIZE(DMA_SIZE_WORD) | DMA_START; } } +#endif /* Update the display. This must be called after all other LCD functions that change the display. */ @@ -397,7 +415,9 @@ void lcd_update(void) { if (display_on) { +#ifndef BOOTLOADER mutex_lock(&lcd_mtx); +#endif lcd_write_reg(R_ENTRY_MODE, R_ENTRY_MODE_VERT); /* set start position window */ @@ -407,8 +427,9 @@ void lcd_update(void) lcd_begin_write_gram(); +#ifndef BOOTLOADER dma_count = 1; - SAR3 = (unsigned long)FBADDR(0,0); + SAR3 = (unsigned long)FBADDR(0, 0); BCR3 = LCD_WIDTH*LCD_HEIGHT*sizeof(fb_data); DCR3 = DMA_INT | DMA_AA | DMA_BWC(1) | DMA_SINC | DMA_SSIZE(DMA_SIZE_LINE) @@ -418,6 +439,17 @@ void lcd_update(void) yield(); mutex_unlock(&lcd_mtx); +#else + DAR3 = 0xf0000002; + SAR3 = (unsigned long)FBADDR(0, 0); + BCR3 = LCD_WIDTH*LCD_HEIGHT*sizeof(fb_data); + DCR3 = DMA_AA | DMA_BWC(1) + | DMA_SINC | DMA_SSIZE(DMA_SIZE_LINE) + | DMA_DSIZE(DMA_SIZE_WORD) | DMA_START; + + while (!(DSR3 & 1)); + DSR3 = 1; +#endif } } @@ -434,7 +466,9 @@ void lcd_update_rect(int x, int y, int width, int height) if (width <= 0 || height <= 0) /* nothing to do */ return; +#ifndef BOOTLOADER mutex_lock(&lcd_mtx); +#endif lcd_write_reg(R_ENTRY_MODE, R_ENTRY_MODE_VERT); /* set update window */ @@ -444,6 +478,7 @@ void lcd_update_rect(int x, int y, int width, int height) lcd_begin_write_gram(); +#ifndef BOOTLOADER if (width == LCD_WIDTH) { dma_count = 1; @@ -453,7 +488,7 @@ void lcd_update_rect(int x, int y, int width, int height) else { dma_count = height; - SAR3 = dma_addr = (unsigned long)FBADDR(x,y); + SAR3 = dma_addr = (unsigned long)FBADDR(x, y); BCR3 = dma_len = width * sizeof(fb_data); } DCR3 = DMA_INT | DMA_AA | DMA_BWC(1) @@ -464,5 +499,24 @@ void lcd_update_rect(int x, int y, int width, int height) yield(); mutex_unlock(&lcd_mtx); +#else + DAR3 = 0xf0000002; + unsigned long dma_addr = (unsigned long)FBADDR(x, y); + width *= sizeof(fb_data); + + for (; height > 0; height--) + { + SAR3 = dma_addr; + BCR3 = width; + DCR3 = DMA_AA | DMA_BWC(1) + | DMA_SINC | DMA_SSIZE(DMA_SIZE_LINE) + | DMA_DSIZE(DMA_SIZE_WORD) | DMA_START; + + dma_addr += LCD_WIDTH*sizeof(fb_data); + + while (!(DSR3 & 1)); + DSR3 = 1; + } +#endif } }