1
0
Fork 0
forked from len0rd/rockbox

M:Robe 500: Add low-level support for vertical strides

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@22599 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Karl Kurbjun 2009-09-02 01:33:32 +00:00
parent 5ac447a9de
commit 6ed463501a

View file

@ -33,14 +33,7 @@
#include "dsp-target.h" #include "dsp-target.h"
#include "dsp/ipc.h" #include "dsp/ipc.h"
#if CONFIG_ORIENTATION == SCREEN_PORTRAIT #define LCD_USE_DMA
#define PORTRAIT_USE_DMA
#else
/* Very slow - May be faster if the DSP has lower latency access to buffer.
Using the DSP instead of ARM to do transformation has not been tried
*/
//#define LANDSCAPE_USE_DMA
#endif
/* Copies a rectangle from one framebuffer to another. Can be used in /* Copies a rectangle from one framebuffer to another. Can be used in
single transfer mode with width = num pixels, and height = 1 which single transfer mode with width = num pixels, and height = 1 which
@ -271,18 +264,21 @@ void lcd_set_mode(int mode)
} }
#endif #endif
#if defined(PORTRAIT_USE_DMA) #if defined(LCD_USE_DMA)
static void dma_start_transfer16( char *src, char *dst, int stride, static void dma_start_transfer16( char *src, int src_x, int src_y, int stride,
int x, int y,
int width, int height, int pix_width) int width, int height, int pix_width)
__attribute__ ((section(".icode"))); __attribute__ ((section(".icode")));
#if CONFIG_ORIENTATION == SCREEN_PORTRAIT
static void dma_start_transfer16( char *src, char *dst, int stride, static void dma_start_transfer16( char *src, int src_x, int src_y, int stride,
int x, int y,
int width, int height, int pix_width) { int width, int height, int pix_width) {
int c_width = width; char *dst;
/* Addresses are relative to start of SDRAM */ /* Addresses are relative to start of SDRAM */
src-=CONFIG_SDRAM_START; src = src + (src_y*LCD_HEIGHT + src_x) * pix_width - CONFIG_SDRAM_START;
dst-=CONFIG_SDRAM_START; dst = (char *)FRAME + (y * LCD_HEIGHT + x) * pix_width
- CONFIG_SDRAM_START;
/* Enable Clocks */ /* Enable Clocks */
IO_CLK_MOD1 |= 1<<8; IO_CLK_MOD1 |= 1<<8;
@ -294,9 +290,9 @@ static void dma_start_transfer16( char *src, char *dst, int stride,
COP_BUF_MUX0 = 0x0663; COP_BUF_MUX0 = 0x0663;
/* Setup buffer offsets and transfer width/height */ /* Setup buffer offsets and transfer width/height */
COP_BUF_LOFST = 32; COP_BUF_LOFST = width;
COP_DMA_XNUM = 32; COP_DMA_XNUM = width;
COP_DMA_YNUM = 32; COP_DMA_YNUM = 1;
/* ... */ /* ... */
COP_IMG_MODE = 0x0000; COP_IMG_MODE = 0x0000;
@ -307,164 +303,109 @@ static void dma_start_transfer16( char *src, char *dst, int stride,
/* Setup SDRAM stride */ /* Setup SDRAM stride */
COP_SDEM_LOFST = stride; COP_SDEM_LOFST = stride;
do { do {
do { int addr;
int addr; addr = (int)src;
addr = (int)src; addr >>= 1; /* Addresses are in 16-bit words */
addr >>= 1; /* Addresses are in 16-bit words */
/* Setup the registers to initiate the read from SDRAM */ /* Setup the registers to initiate the read from SDRAM */
COP_SDEM_ADDRH = addr >> 16; COP_SDEM_ADDRH = addr >> 16;
COP_SDEM_ADDRL = addr & 0xFFFF; COP_SDEM_ADDRL = addr & 0xFFFF;
/* Set direction and start */ /* Set direction and start */
COP_DMA_CTRL = 0x0001; COP_DMA_CTRL = 0x0001;
COP_DMA_CTRL |= 0x0003; COP_DMA_CTRL |= 0x0003;
/* Wait for read to finish */ /* Wait for read to finish */
while(COP_DMA_CTRL & 0x02) {}; while(COP_DMA_CTRL & 0x02) {};
addr = (int)dst; addr = (int)dst;
addr >>= 1; addr >>= 1;
COP_SDEM_ADDRH = addr >> 16; COP_SDEM_ADDRH = addr >> 16;
COP_SDEM_ADDRL = addr & 0xFFFF; COP_SDEM_ADDRL = addr & 0xFFFF;
/* Set direction and start transfer */ /* Set direction and start transfer */
COP_DMA_CTRL = 0x0000; COP_DMA_CTRL = 0x0000;
COP_DMA_CTRL = 0x0002; COP_DMA_CTRL = 0x0002;
/* Wait for the transfer to complete */ /* Wait for the transfer to complete */
while(COP_DMA_CTRL & 0x02) {}; while(COP_DMA_CTRL & 0x02) {};
/* Update source and destination pointers/counters */ /* Decrease height, update pointers/counters */
src += 32*pix_width; src += (stride*pix_width);
dst += 32*pix_width; dst += (stride*pix_width);
c_width -= 32; height--;
} while (c_width>0);
/* Reset the width, update pointers/counters */
c_width = width;
src -= width*pix_width;
dst -= width*pix_width;
src += (LCD_WIDTH*32*pix_width);
dst += (LCD_WIDTH*32*pix_width);
height -= 32;
} while(height>0); } while(height>0);
} }
#endif #else
static void dma_start_transfer16( char *src, int src_x, int src_y, int stride,
#if defined(LANDSCAPE_USE_DMA) int x, int y,
static void dma_start_transfer16_r( char *src, int sx, int sy, int sstride,
char *dst, int dx, int dy, int dstride,
int width, int height, int pix_width) { int width, int height, int pix_width) {
if(sx & 0x0F) { char *dst;
int sx2 = sx + width; /* Addresses are relative to start of SDRAM */
src = src + (src_x*LCD_HEIGHT + src_y) * pix_width - CONFIG_SDRAM_START;
if(sx2 & 0x0F) { dst = (char *)FRAME + (LCD_HEIGHT*(LCD_WIDTH-1) - x * LCD_HEIGHT + y)
sx2 = (sx2 + 0x0F) & ~0x0F; * pix_width - CONFIG_SDRAM_START;
}
sx = sx & ~0x0F;
width = sx2 - sx;
}
if(sy & 0x0F) {
int sy2 = sy + height;
if(sy2 & 0x0F) {
sy2 = (sy2 + 0x0F) & ~0x0F;
}
sy = sy & ~0x0F;
height = sy2 - sy;
}
if(dx & 0x0F) {
dx = dx & ~0x0F;
}
if(dy & 0x0F) {
dy = dy & ~0x0F;
}
src=src+(sy*sstride+sx)*pix_width;
dst=dst + ((LCD_NATIVE_WIDTH*(LCD_NATIVE_HEIGHT-1))
- LCD_NATIVE_WIDTH*(dx+32) + dy)*pix_width;
int c_width = width;
/* Enable Clocks */
IO_CLK_MOD1 |= 1<<8; IO_CLK_MOD1 |= 1<<8;
COP_CP_CLKC |= 0x0001; COP_CP_CLKC |= 0x0001;
/* ... */
COP_BUF_MUX1 = 0x0005; COP_BUF_MUX1 = 0x0005;
/* Give the DMA access to the buffer */ /* Give the DMA access to the buffer */
COP_BUF_MUX0 = 0x0663; COP_BUF_MUX0 = 0x0663;
/* Set the buffer offsets and widths */ /* Setup buffer offsets and transfer width/height */
COP_BUF_LOFST = 32; COP_BUF_LOFST = height;
COP_DMA_XNUM = 32; COP_DMA_XNUM = height;
COP_DMA_YNUM = 32; COP_DMA_YNUM = 1;
/* ... */
COP_IMG_MODE = 0x0000; COP_IMG_MODE = 0x0000;
/* Set the start address of buffer */
COP_BUF_ADDR = 0x0000;
/* Setup SDRAM stride */
COP_SDEM_LOFST = stride;
do { do {
char *c_dst = dst; int addr;
do { addr = (int)src;
int addr; addr >>= 1; /* Addresses are in 16-bit words */
COP_BUF_ADDR = 0x0000; /* Setup the registers to initiate the read from SDRAM */
COP_SDEM_ADDRH = addr >> 16;
COP_SDEM_ADDRL = addr & 0xFFFF;
COP_SDEM_LOFST = sstride; /* Set direction and start */
addr = (int)src - CONFIG_SDRAM_START; COP_DMA_CTRL = 0x0001;
addr >>= 1; COP_DMA_CTRL |= 0x0003;
COP_SDEM_ADDRH = addr >> 16; /* Wait for read to finish */
COP_SDEM_ADDRL = addr & 0xFFFF; while(COP_DMA_CTRL & 0x02) {};
COP_DMA_CTRL = 0x0001; addr = (int)dst;
COP_DMA_CTRL |= 0x0003; addr >>= 1;
while(COP_DMA_CTRL & 0x02) {}; COP_SDEM_ADDRH = addr >> 16;
COP_SDEM_ADDRL = addr & 0xFFFF;
/* The ARM can access the buffer after this is set */ /* Set direction and start transfer */
COP_BUF_MUX0 = 0x0660; COP_DMA_CTRL = 0x0000;
COP_DMA_CTRL = 0x0002;
int run=1023; /* Wait for the transfer to complete */
#define IMG_BUF (*(volatile unsigned short *)(0x80000)) while(COP_DMA_CTRL & 0x02) {};
#define IMG_BUF2 (*(volatile unsigned short *)(0x80000 + 2*32*32 + 32*31*2 ))
do {
*(&IMG_BUF2-((run&0x1F)<<5)+(run>>5)) = *(&IMG_BUF+run);
} while(run--);
COP_BUF_MUX0 = 0x0663; /* update the width, update pointers/counters */
src += (stride*pix_width);
COP_BUF_ADDR = (32*32); dst -= (stride*pix_width);
width--;
COP_SDEM_LOFST = LCD_NATIVE_WIDTH; } while(width>0);
addr = (int)c_dst - CONFIG_SDRAM_START;
addr >>= 1;
COP_SDEM_ADDRH = addr >> 16;
COP_SDEM_ADDRL = addr & 0xFFFF;
COP_DMA_CTRL = 0x0000;
COP_DMA_CTRL = 0x0002;
while(COP_DMA_CTRL & 0x02) {};
src += 32*pix_width;
c_dst -= 32*pix_width*LCD_NATIVE_WIDTH;
c_width -= 32;
} while (c_width>0);
c_width = width;
src += (LCD_WIDTH*31*pix_width);
dst += (32*pix_width);
height -= 32;
} while(height>0);
} }
#endif #endif
#endif
/* Update a fraction of the display. */ /* Update a fraction of the display. */
void lcd_update_rect(int x, int y, int width, int height) void lcd_update_rect(int x, int y, int width, int height)
@ -488,37 +429,10 @@ void lcd_update_rect(int x, int y, int width, int height)
height += y, y = 0; /* Clip top */ height += y, y = 0; /* Clip top */
#if CONFIG_ORIENTATION == SCREEN_PORTRAIT #if CONFIG_ORIENTATION == SCREEN_PORTRAIT
#if defined(PORTRAIT_USE_DMA)
/* Makes sure the update is a ratio of 32x32 */
if(x & 0x1F) {
int x2 = x + width;
if(x2 & 0x1F) { #if defined(LCD_USE_DMA)
x2 = (x2 + 0x1F) & ~0x1F; dma_start_transfer16( (char *)lcd_framebuffer, x, y, LCD_WIDTH,
} x, y, width, height, 2);
x = x & ~0x1F;
width = x2 - x;
}
if(y & 0x1F) {
int y2 = y + height;
if(y2 & 0x1F) {
y2 += 0x1F;
y2 &= ~0x1F;
}
y = y & ~0x1F;
height = y2 - y;
}
fb_data *dst;
dst = (fb_data *)FRAME + LCD_WIDTH*y + x;
dma_start_transfer16( (char *)&lcd_framebuffer[y][x],(char *)dst,
LCD_WIDTH, width, height, 2);
#else #else
register fb_data *dst; register fb_data *dst;
@ -536,11 +450,12 @@ void lcd_update_rect(int x, int y, int width, int height)
lcd_copy_buffer_rect(dst, &lcd_framebuffer[y][x], LCD_WIDTH*height, 1); lcd_copy_buffer_rect(dst, &lcd_framebuffer[y][x], LCD_WIDTH*height, 1);
} }
#endif #endif
#else #else
#if defined(LANDSCAPE_USE_DMA)
dma_start_transfer16_r( (char *)lcd_framebuffer, 0, 0, LCD_WIDTH, #if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
(char *)FRAME, 0, 0, LCD_NATIVE_WIDTH, dma_start_transfer16( (char *)lcd_framebuffer, x, y, LCD_HEIGHT,
LCD_WIDTH, LCD_HEIGHT, 2); x, y, width, height, 2);
#else #else
register fb_data *dst, *src; register fb_data *dst, *src;
src = &lcd_framebuffer[y][x]; src = &lcd_framebuffer[y][x];
@ -562,6 +477,7 @@ void lcd_update_rect(int x, int y, int width, int height)
dst++; dst++;
} while(height--); } while(height--);
#endif #endif
#endif #endif
} }
@ -583,12 +499,11 @@ void lcd_blit_pal256(unsigned char *src, int src_x, int src_y, int x, int y,
int width, int height) int width, int height)
{ {
#if CONFIG_ORIENTATION == SCREEN_PORTRAIT #if CONFIG_ORIENTATION == SCREEN_PORTRAIT
#if defined(PORTRAIT_USE_DMA) #if defined(LCD_USE_DMA)
src = src+src_x+src_y*LCD_WIDTH; // char *dst=(char *)FRAME+x+y*(LCD_NATIVE_WIDTH+LCD_FUDGE);
char *dst=(char *)FRAME+x+y*(LCD_NATIVE_WIDTH+LCD_FUDGE);
dma_start_transfer16( (char *)src, (char *)dst, LCD_WIDTH>>1, dma_start_transfer16( src, src_x, src_y, LCD_WIDTH,
width, height, 1); x, y, width, height, 1);
#else #else
char *dst=(char *)FRAME+x+y*(LCD_NATIVE_WIDTH+LCD_FUDGE); char *dst=(char *)FRAME+x+y*(LCD_NATIVE_WIDTH+LCD_FUDGE);