diff options
Diffstat (limited to 'firmware/target/arm/tms320dm320')
-rw-r--r-- | firmware/target/arm/tms320dm320/sansa-connect/lcd-sansaconnect.c | 124 | ||||
-rw-r--r-- | firmware/target/arm/tms320dm320/sansa-connect/lcd-target.h | 8 |
2 files changed, 132 insertions, 0 deletions
diff --git a/firmware/target/arm/tms320dm320/sansa-connect/lcd-sansaconnect.c b/firmware/target/arm/tms320dm320/sansa-connect/lcd-sansaconnect.c index ad417663fe..d4d5b97ca7 100644 --- a/firmware/target/arm/tms320dm320/sansa-connect/lcd-sansaconnect.c +++ b/firmware/target/arm/tms320dm320/sansa-connect/lcd-sansaconnect.c @@ -153,6 +153,130 @@ void lcd_init_device(void) lcd_on = true; } +#ifdef LCD_USE_DMA +static void dma_lcd_copy_buffer_rect(int x, int y, int width, int height) +{ + char *dst, *src; + + /* Image buffer A is 4KW, every pixel is one Word */ + /* lines is maximum number of lines we can transfer in single run */ + int lines = 4096/width; + if (lines > height) + lines = height; + + /* Set source and destination addresses */ + dst = (char*)(FRAME + LCD_WIDTH*y + x); + src = (char*)(&lcd_framebuffer[y][x]); + + /* Flush cache to memory */ + commit_dcache(); + + /* Addresses are relative to start of SDRAM */ + src -= CONFIG_SDRAM_START; + dst -= CONFIG_SDRAM_START; + + /* Enable Image Buffer clock */ + bitset16(&IO_CLK_MOD1, CLK_MOD1_IMGBUF); + + /* Use Image Buffer A for DMA */ + COP_BUF_MUX0 = (COP_BUF_MUX0 & 0xFFF0) | 0x0003; + + /* Setup buffer offsets and transfer width/height */ + COP_BUF_LOFST = width; + COP_DMA_XNUM = width; + COP_DMA_YNUM = lines; + + /* DMA: No byte SWAP, no transformation, data bus shift down 0 bit */ + COP_IMG_MODE &= 0xC0; + + /* Set the start address of buffer */ + COP_BUF_ADDR = 0x0000; + + /* Setup SDRAM stride */ + COP_SDEM_LOFST = LCD_WIDTH; + + do { + int addr; + + addr = (int)src; + addr >>= 1; /* Addresses are in 16-bit words */ + + /* Setup the registers to initiate the read from SDRAM */ + COP_SDEM_ADDRH = addr >> 16; + COP_SDEM_ADDRL = addr & 0xFFFF; + + /* Set direction and start */ + COP_DMA_CTRL = 0x0001; + COP_DMA_CTRL |= 0x0002; + + /* Wait for read to finish */ + while (COP_DMA_CTRL & 0x02) {}; + + addr = (int)dst; + addr >>= 1; + + COP_SDEM_ADDRH = addr >> 16; + COP_SDEM_ADDRL = addr & 0xFFFF; + + /* Set direction and start transfer */ + COP_DMA_CTRL = 0x0000; + COP_DMA_CTRL |= 0x0002; + + /* Wait for the transfer to complete */ + while (COP_DMA_CTRL & 0x02) {}; + + /* Decrease height, update pointers */ + src += (LCD_WIDTH << 1)*lines; + dst += (LCD_WIDTH << 1)*lines; + + height -= lines; + if (height < lines) + { + lines = height; + COP_DMA_YNUM = height; + } + } while (height > 0); + + /* Disable Image Buffer clock */ + bitclr16(&IO_CLK_MOD1, CLK_MOD1_IMGBUF); +} + +/* Update a fraction of the display. */ +void lcd_update_rect(int x, int y, int width, int height) + __attribute__ ((section(".icode"))); +void lcd_update_rect(int x, int y, int width, int height) +{ + if (!lcd_on) + return; + + if ((width | height) < 0) + return; /* Nothing left to do */ + + if (x + width > LCD_WIDTH) + width = LCD_WIDTH - x; /* Clip right */ + if (x < 0) + width += x, x = 0; /* Clip left */ + + if (y + height > LCD_HEIGHT) + height = LCD_HEIGHT - y; /* Clip bottom */ + if (y < 0) + height += y, y = 0; /* Clip top */ + + dma_lcd_copy_buffer_rect(x, y, width, height); +} + +/* Update the display. + This must be called after all other LCD functions that change the display. */ +void lcd_update(void) __attribute__ ((section(".icode"))); +void lcd_update(void) +{ + if (!lcd_on) + return; + + lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); +} +#endif + void lcd_set_contrast(int val) { (void) val; // TODO: diff --git a/firmware/target/arm/tms320dm320/sansa-connect/lcd-target.h b/firmware/target/arm/tms320dm320/sansa-connect/lcd-target.h index 60d5df69c8..6a62140b27 100644 --- a/firmware/target/arm/tms320dm320/sansa-connect/lcd-target.h +++ b/firmware/target/arm/tms320dm320/sansa-connect/lcd-target.h @@ -24,6 +24,14 @@ #define LCD_FRAMEBUF_ADDR(col, row) ((fb_data *)FRAME + (row)*LCD_WIDTH + (col)) +/* Comment this to remove Image Buffer DMA usage */ +#define LCD_USE_DMA + +#ifdef LCD_USE_DMA +#define LCD_OPTIMIZED_UPDATE +#define LCD_OPTIMIZED_UPDATE_RECT +#endif + void lcd_awake(void); #endif /* LCD_TARGET_H */ |