diff --git a/apps/plugin.c b/apps/plugin.c index 17e9ac670b..087bf74a38 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -636,6 +636,13 @@ static const struct plugin_api rockbox_api = { #if defined(HAVE_LCD_MODES) lcd_set_mode, #endif + +#if defined(HAVE_LCD_MODES) +#if HAVE_LCD_MODES & LCD_MODE_PAL256 + lcd_blit_pal256, + lcd_pal256_update_pal, +#endif +#endif }; int plugin_load(const char* plugin, const void* parameter) diff --git a/apps/plugin.h b/apps/plugin.h index fdcf3c2afa..d38cc42ee7 100644 --- a/apps/plugin.h +++ b/apps/plugin.h @@ -794,6 +794,14 @@ struct plugin_api { #if defined(HAVE_LCD_MODES) void (*lcd_set_mode)(int mode); #endif + +#if defined(HAVE_LCD_MODES) +#if HAVE_LCD_MODES & LCD_MODE_PAL256 + void (*lcd_blit_pal256)(unsigned char *src, int src_x, int src_y, int x, int y, + int width, int height); + void (*lcd_pal256_update_pal)(fb_data *palette); +#endif +#endif }; /* plugin header */ diff --git a/apps/plugins/doom/i_video.c b/apps/plugins/doom/i_video.c index c148d17077..418fcd4404 100644 --- a/apps/plugins/doom/i_video.c +++ b/apps/plugins/doom/i_video.c @@ -140,6 +140,12 @@ static fb_data *paldata=NULL; // void I_ShutdownGraphics(void) { +#if defined(HAVE_LCD_MODES) +#if (HAVE_LCD_MODES & LCD_MODE_PAL256) + rb->lcd_set_mode(LCD_MODE_RGB565); +#endif +#endif + #ifndef HAVE_LCD_COLOR grey_release(); #endif @@ -597,13 +603,19 @@ static void I_UploadNewPalette(int pal) } #ifdef RANGECHECK - if ((size_t)pal >= num_pals) - I_Error("I_UploadNewPalette: Palette number out of range (%d>=%d)", - pal, num_pals); + if ((size_t)pal >= num_pals) + I_Error("I_UploadNewPalette: Palette number out of range (%d>=%d)", + pal, num_pals); #endif - memcpy(palette,paldata+256*pal,256*sizeof(fb_data)); -} + memcpy(palette,paldata+256*pal,256*sizeof(fb_data)); + +#if defined(HAVE_LCD_MODES) +#if (HAVE_LCD_MODES & LCD_MODE_PAL256) + rb->lcd_pal256_update_pal(paldata+256*pal); +#endif +#endif +} // // I_FinishUpdate @@ -613,36 +625,37 @@ void I_FinishUpdate (void) { int count; byte *src = d_screens[0]; + #if (CONFIG_LCD == LCD_H300) && !defined(SIMULATOR) count = SCREENWIDTH*SCREENHEIGHT; /* ASM screen update (drops ~300 tics) */ asm volatile ( - "move.w #33, (%[LCD]) \n" /* Setup the LCD controller */ - "nop \n" - "clr.w (%[LCD2]) \n" - "nop \n" - "move.w #34, (%[LCD]) \n" /* End LCD controller setup */ - "clr.l %%d1 \n" - ".loop: \n" - "move.l (%[scrp])+, %%d0 \n" - "swap.w %%d0 \n" - "move.w %%d0, %%d1 \n" - "lsr.l #8,%%d1 \n" - "move.w (%[pal], %%d1.l:2), (%[LCD2]) \n" - "move.b %%d0,%%d1 \n" - "swap.w %%d0 \n" - "nop \n" - "move.w (%[pal], %%d1.l:2), (%[LCD2]) \n" - "move.w %%d0, %%d1 \n" - "lsr.l #8,%%d1 \n" - "nop \n" - "move.w (%[pal], %%d1.l:2), (%[LCD2]) \n" - "move.b %%d0,%%d1 \n" - "nop \n" - "move.w (%[pal], %%d1.l:2), (%[LCD2]) \n" - "subq.l #4,%[cnt] \n" - "bne.b .loop \n" + "move.w #33, (%[LCD]) \n" /* Setup the LCD controller */ + "nop \n" + "clr.w (%[LCD2]) \n" + "nop \n" + "move.w #34, (%[LCD]) \n" /* End LCD controller setup */ + "clr.l %%d1 \n" + ".loop: \n" + "move.l (%[scrp])+, %%d0 \n" + "swap.w %%d0 \n" + "move.w %%d0, %%d1 \n" + "lsr.l #8,%%d1 \n" + "move.w (%[pal], %%d1.l:2), (%[LCD2]) \n" + "move.b %%d0,%%d1 \n" + "swap.w %%d0 \n" + "nop \n" + "move.w (%[pal], %%d1.l:2), (%[LCD2]) \n" + "move.w %%d0, %%d1 \n" + "lsr.l #8,%%d1 \n" + "nop \n" + "move.w (%[pal], %%d1.l:2), (%[LCD2]) \n" + "move.b %%d0,%%d1 \n" + "nop \n" + "move.w (%[pal], %%d1.l:2), (%[LCD2]) \n" + "subq.l #4,%[cnt] \n" + "bne.b .loop \n" : /* outputs */ [scrp]"+a"(src), [cnt] "+d"(count) @@ -713,7 +726,14 @@ void I_FinishUpdate (void) "d0", "d1", "d2", "d3" ); #else -#ifdef HAVE_LCD_COLOR + +/* If the hardware has support for a paletted mode it takes precidence */ +#if defined(HAVE_LCD_MODES) +#if (HAVE_LCD_MODES & LCD_MODE_PAL256) + (void) count; + rb->lcd_blit_pal256(src, 0, 0, 0, 0, LCD_WIDTH, LCD_HEIGHT); +#endif +#elif defined(HAVE_LCD_COLOR) #if(LCD_HEIGHT>LCD_WIDTH) if(rotate_screen) { @@ -742,8 +762,9 @@ void I_FinishUpdate (void) *dst++ = palette[*src++]; while (--count); } - rb->lcd_update(); + rb->lcd_update(); #else /* !HAVE_LCD_COLOR */ + unsigned char *dst; int y; @@ -758,8 +779,8 @@ void I_FinishUpdate (void) grey_ub_gray_bitmap(greybuffer, 0, y, SCREENWIDTH, 1); } -#endif /* !HAVE_LCD_COLOR */ -#endif +#endif +#endif } // @@ -786,6 +807,12 @@ void I_InitGraphics(void) printf("Starting Graphics engine\n"); noprintf=1; + +#if defined(HAVE_LCD_MODES) +#if (HAVE_LCD_MODES & LCD_MODE_PAL256) + rb->lcd_set_mode(LCD_MODE_PAL256); +#endif +#endif /* Note: The other screens are allocated as needed */ diff --git a/apps/plugins/plugin.lds b/apps/plugins/plugin.lds index 9c65f31779..d6f62341ce 100644 --- a/apps/plugins/plugin.lds +++ b/apps/plugins/plugin.lds @@ -35,18 +35,20 @@ OUTPUT_FORMAT(elf32-littlemips) #define NOCACHE_BASE 0x00000000 #endif -#if CONFIG_CPU==DM320 || CONFIG_CPU==S3C2440 -#define LCD_BUFFER_SIZE (LCD_WIDTH*LCD_HEIGHT*2) +#if CONFIG_CPU==DM320 || CONFIG_CPU==IMX31L +/* Give this 1 meg to allow it to align to the MMU boundary */ +#define LCD_TTB_AREA 0x100000 +#define DRAMSIZE (MEMORYSIZE * 0x100000) - STUBOFFSET - PLUGIN_BUFFER_SIZE - CODEC_SIZE - LCD_TTB_AREA +#elif CONFIG_CPU==S3C2440 +#define LCD_BUFFER_SIZE (LCD_WIDTH*LCD_HEIGHT*2) /* must be 16Kb (0x4000) aligned */ #define TTB_SIZE (0x4000) #define DRAMSIZE (MEMORYSIZE * 0x100000) - STUBOFFSET - PLUGIN_BUFFER_SIZE - CODEC_SIZE - LCD_BUFFER_SIZE - TTB_SIZE -#elif CONFIG_CPU==IMX31L -#include "imx31l.h" -/* Reserve 1mb for LCD buffer/TTB as in app.lds */ -#define DRAMSIZE (MEMORYSIZE * 0x100000 - 0x100000) - PLUGIN_BUFFER_SIZE - STUBOFFSET - CODEC_SIZE + #elif CONFIG_CPU==AS3525 && MEMORYSIZE <= 2 #define DRAMSIZE (MEMORYSIZE * 0x100000) - PLUGIN_BUFFER_SIZE - STUBOFFSET + #else #define DRAMSIZE (MEMORYSIZE * 0x100000) - PLUGIN_BUFFER_SIZE - STUBOFFSET - CODEC_SIZE #endif @@ -77,11 +79,7 @@ OUTPUT_FORMAT(elf32-littlemips) #define DRAMORIG 0xc00000 + STUBOFFSET #define IRAMORIG 0x407000 #define IRAMSIZE 0x9000 -#elif CONFIG_CPU == S3C2440 -#define DRAMORIG 0x0 + STUBOFFSET -#define IRAM DRAM -#define IRAMSIZE 0 -#elif CONFIG_CPU == IMX31L +#elif CONFIG_CPU == IMX31L || CONFIG_CPU == S3C2440 #define DRAMORIG 0x0 + STUBOFFSET #define IRAM DRAM #define IRAMSIZE 0 diff --git a/firmware/export/config-mrobe500.h b/firmware/export/config-mrobe500.h index fafea48a94..90bbefe329 100644 --- a/firmware/export/config-mrobe500.h +++ b/firmware/export/config-mrobe500.h @@ -59,24 +59,21 @@ /* LCD dimensions */ #define CONFIG_LCD LCD_MROBE500 -/* choose the lcd orientation. both work */ -/* #define CONFIG_ORIENTATION SCREEN_PORTRAIT */ -#define CONFIG_ORIENTATION SCREEN_PORTRAIT - -#if 1 -#define NATIVE_MAX_WIDTH 480 -#define NATIVE_MAX_HEIGHT 640 +#if 0 +#define LCD_NATIVE_WIDTH 480 +#define LCD_NATIVE_HEIGHT 640 #else -#define NATIVE_MAX_WIDTH 240 -#define NATIVE_MAX_HEIGHT 320 +#define LCD_NATIVE_WIDTH 240 +#define LCD_NATIVE_HEIGHT 320 #endif -#if CONFIG_ORIENTATION == SCREEN_PORTRAIT -#define LCD_WIDTH NATIVE_MAX_WIDTH -#define LCD_HEIGHT NATIVE_MAX_HEIGHT +/* choose the lcd orientation. CONFIG_ORIENTATION defined in config.h */ +#if 0 +#define LCD_WIDTH LCD_NATIVE_WIDTH +#define LCD_HEIGHT LCD_NATIVE_HEIGHT #else -#define LCD_WIDTH NATIVE_MAX_HEIGHT -#define LCD_HEIGHT NATIVE_MAX_WIDTH +#define LCD_WIDTH LCD_NATIVE_HEIGHT +#define LCD_HEIGHT LCD_NATIVE_WIDTH #endif #define LCD_DEPTH 16 /* 65k colours */ @@ -142,16 +139,20 @@ #define HW_SAMPR_CAPS SAMPR_CAP_44 -#define BATTERY_CAPACITY_DEFAULT 1100 /* default battery capacity */ -#define BATTERY_CAPACITY_MIN 500 /* min. capacity selectable */ -#define BATTERY_CAPACITY_MAX 2500 /* max. capacity selectable */ +#define BATTERY_CAPACITY_DEFAULT 1500 /* default battery capacity */ +#define BATTERY_CAPACITY_MIN 1000 /* min. capacity selectable */ +#define BATTERY_CAPACITY_MAX 2000 /* max. capacity selectable */ #define BATTERY_CAPACITY_INC 100 /* capacity increment */ #define BATTERY_TYPES_COUNT 1 /* only one type */ +/* define current usage levels */ +#define CURRENT_NORMAL 120 /* Measured */ +#define CURRENT_BACKLIGHT 80 /* Over 200 mA total measured when on */ +#define CURRENT_RECORD 0 /* no recording */ + /* Hardware controlled charging with monitoring */ #define CONFIG_CHARGING CHARGING_MONITOR - /* Define this if you have a Texas Instruments TSC2100 touch screen */ #define HAVE_TSC2100 diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h index 4f35927353..e52356b8bf 100644 --- a/firmware/export/lcd.h +++ b/firmware/export/lcd.h @@ -97,7 +97,14 @@ void lcd_set_mode(int mode); #define LCD_MODE_RGB565 0x00000001 #define LCD_MODE_YUV 0x00000002 #define LCD_MODE_PAL256 0x00000004 + +#if HAVE_LCD_MODES & LCD_MODE_PAL256 + void lcd_blit_pal256(unsigned char *src, int src_x, int src_y, int x, int y, + int width, int height); + void lcd_pal256_update_pal(fb_data *palette); #endif +#endif + /* common functions */ extern void lcd_write_command(int byte); diff --git a/firmware/target/arm/tms320dm320/app.lds b/firmware/target/arm/tms320dm320/app.lds index 47ff239a1a..4e175101a9 100644 --- a/firmware/target/arm/tms320dm320/app.lds +++ b/firmware/target/arm/tms320dm320/app.lds @@ -6,35 +6,30 @@ OUTPUT_FORMAT(elf32-littlearm) OUTPUT_ARCH(arm) STARTUP(target/arm/tms320dm320/crt0.o) -#define PLUGINSIZE PLUGIN_BUFFER_SIZE -#define CODECSIZE CODEC_SIZE - #ifdef DEBUG #define STUBOFFSET 0x10000 #else #define STUBOFFSET 0 #endif -#define LCD_BUFFER_SIZE (LCD_WIDTH*LCD_HEIGHT*2) +#define LCD_FUDGE LCD_NATIVE_WIDTH%32 + +#define LCD_BUFFER_SIZE ((LCD_NATIVE_WIDTH+LCD_FUDGE)*LCD_NATIVE_HEIGHT*2) /* must be 16Kb (0x4000) aligned */ -#define TTB_SIZE (0x4000) +#define TTB_SIZE 0x4000 -#define DRAMSIZE (MEMORYSIZE * 0x100000) - STUBOFFSET - PLUGINSIZE - CODECSIZE - LCD_BUFFER_SIZE - TTB_SIZE +/* Give this 1 meg to allow it to align to the MMU boundary */ +#define LCD_TTB_AREA 0x100000 -#define DRAMORIG 0x00900000 + STUBOFFSET -#define IRAMORIG 0x00000000 -#define IRAMSIZE 0x4000 +#define DRAMSIZE (MEMORYSIZE * 0x100000) - STUBOFFSET + +#define DRAMORIG 0x00900000 + STUBOFFSET +#define IRAMORIG 0x00000000 +#define IRAMSIZE 0x4000 /* End of the audio buffer, where the codec buffer starts */ -#define ENDAUDIOADDR (DRAMORIG + DRAMSIZE) - -/* Where the codec buffer ends, and the plugin buffer starts */ -#define ENDADDR (ENDAUDIOADDR + CODECSIZE) - -#define LCDBEGIN (ENDADDR + PLUGINSIZE) - -#define TTBBEGIN (LCDBEGIN + LCD_BUFFER_SIZE) +#define ENDAUDIOADDR (DRAMORIG + DRAMSIZE - PLUGIN_BUFFER_SIZE - CODEC_SIZE - LCD_TTB_AREA) MEMORY { @@ -144,22 +139,32 @@ SECTIONS { codecbuf = .; _codecbuf = .; - } + . += CODEC_SIZE; + } > DRAM - .plugin ENDADDR (NOLOAD) : + .plugin (NOLOAD) : { _pluginbuf = .; pluginbuf = .; - } + . += PLUGIN_BUFFER_SIZE; + } > DRAM - .lcdbuffer LCDBEGIN (NOLOAD) : + .ttbtable (NOLOAD) : + { + . = ALIGN (0x4000); + _ttbstart = .; + . += TTB_SIZE; + } > DRAM + + /* The LCD buffer should be at the end of memory to protect against + * overflowing something else when the YUV blitter is fudging the screen + * size. + */ + + .lcdbuffer (NOLOAD) : { _lcdbuf = .; - } - - .ttbtable TTBBEGIN (NOLOAD) : - { - _ttbstart = .; - } + . += LCD_BUFFER_SIZE; + } > DRAM } diff --git a/firmware/target/arm/tms320dm320/mrobe-500/lcd-mr500.c b/firmware/target/arm/tms320dm320/mrobe-500/lcd-mr500.c index 3fa8a7e6c1..1334eeaf8d 100644 --- a/firmware/target/arm/tms320dm320/mrobe-500/lcd-mr500.c +++ b/firmware/target/arm/tms320dm320/mrobe-500/lcd-mr500.c @@ -112,6 +112,11 @@ void lcd_enable(bool state) } #endif +/* Note this is expecting a screen size of 480x640 or 240x320, other screen + * sizes need to be considered for fudge factors + */ +#define LCD_FUDGE LCD_NATIVE_WIDTH%32 + /* LCD init - based on code from ingenient-bsp/bootloader/board/dm320/splash.c * and code by Catalin Patulea from the M:Robe 500i linux port */ @@ -122,21 +127,26 @@ void lcd_init_device(void) /* Clear the Frame */ memset16(FRAME, 0x0000, LCD_WIDTH*LCD_HEIGHT); + lcd_sleep(); + + IO_OSD_OSDWINMD0&=~(0x0001); + IO_OSD_VIDWINMD&=~(0x0001); + /* Setup the LCD controller */ - IO_VID_ENC_VMOD=0x2015; + IO_VID_ENC_VMOD=0x2014; IO_VID_ENC_VDCTL=0x2000; IO_VID_ENC_VDPRO=0x0000; IO_VID_ENC_SYNCTL=0x100E; IO_VID_ENC_HSPLS=1; /* HSYNC pulse width */ IO_VID_ENC_VSPLS=1; /* VSYNC pulse width */ - /* These calculations support 640x480 and 320x240 */ - IO_VID_ENC_HINT=NATIVE_MAX_WIDTH+NATIVE_MAX_WIDTH/3; - IO_VID_ENC_HSTART=NATIVE_MAX_WIDTH/6; /* Front porch */ - IO_VID_ENC_HVALID=NATIVE_MAX_WIDTH; /* Data valid */ - IO_VID_ENC_VINT=NATIVE_MAX_HEIGHT+7; + /* These calculations support 640x480 and 320x240 (based on OF) */ + IO_VID_ENC_HINT=LCD_NATIVE_WIDTH+LCD_NATIVE_WIDTH/3; + IO_VID_ENC_HSTART=LCD_NATIVE_WIDTH/6; /* Front porch */ + IO_VID_ENC_HVALID=LCD_NATIVE_WIDTH; /* Data valid */ + IO_VID_ENC_VINT=LCD_NATIVE_HEIGHT+7; IO_VID_ENC_VSTART=3; - IO_VID_ENC_VVALID=NATIVE_MAX_HEIGHT; + IO_VID_ENC_VVALID=LCD_NATIVE_HEIGHT; IO_VID_ENC_HSDLY=0x0000; IO_VID_ENC_VSDLY=0x0000; @@ -152,46 +162,88 @@ void lcd_init_device(void) IO_VID_ENC_PWMP=0x0000; IO_VID_ENC_PWMW=0x0000; - IO_VID_ENC_DCLKCTL=0x0800; IO_VID_ENC_DCLKPTN0=0x0001; - /* Setup the display */ IO_OSD_MODE=0x00ff; - IO_OSD_VIDWINMD=0x0002; - IO_OSD_OSDWINMD0=0x2001; - IO_OSD_OSDWINMD1=0x0002; + IO_OSD_ATRMD=0x0000; IO_OSD_RECTCUR=0x0000; - - IO_OSD_OSDWIN0OFST=(NATIVE_MAX_WIDTH*2) / 32; - addr = ((int)FRAME-CONFIG_SDRAM_START) / 32; - IO_OSD_OSDWINADH=addr >> 16; - IO_OSD_OSDWIN0ADL=addr & 0xFFFF; - - IO_OSD_VIDWINADH=addr >> 16; - IO_OSD_VIDWIN0ADL=addr & 0xFFFF; - IO_OSD_BASEPX=IO_VID_ENC_HSTART; IO_OSD_BASEPY=IO_VID_ENC_VSTART; + + addr = ((int)FRAME-CONFIG_SDRAM_START) / 32; + + /* Setup the OSD windows */ + + /* Used for 565 RGB */ + IO_OSD_OSDWINMD0=0x30C0; + + IO_OSD_OSDWIN0OFST=LCD_NATIVE_WIDTH / 16; + + IO_OSD_OSDWINADH=addr >> 16; + IO_OSD_OSDWIN0ADL=addr & 0xFFFF; IO_OSD_OSDWIN0XP=0; IO_OSD_OSDWIN0YP=0; - - IO_OSD_OSDWIN0XL=NATIVE_MAX_WIDTH; - IO_OSD_OSDWIN0YL=NATIVE_MAX_HEIGHT; + + /* read from OF */ + IO_OSD_OSDWIN0XL=LCD_NATIVE_WIDTH; + IO_OSD_OSDWIN0YL=LCD_NATIVE_HEIGHT; + + /* Unused */ + IO_OSD_OSDWINMD1=0x10C0; + +#if LCD_NATIVE_WIDTH%32!=0 + IO_OSD_OSDWIN1OFST=LCD_NATIVE_WIDTH / 32+1; +#else + IO_OSD_OSDWIN1OFST=LCD_NATIVE_WIDTH / 32; +#endif + + IO_OSD_OSDWIN1ADL=addr & 0xFFFF; + + IO_OSD_OSDWIN1XP=0; + IO_OSD_OSDWIN1YP=0; + + IO_OSD_OSDWIN1XL=LCD_NATIVE_WIDTH; + IO_OSD_OSDWIN1YL=LCD_NATIVE_HEIGHT; + + IO_OSD_VIDWINMD=0x0002; + + /* This is a bit messy, the LCD transfers appear to happen in chunks of 32 + * pixels. (based on OF) + */ +#if LCD_NATIVE_WIDTH%32!=0 + IO_OSD_VIDWIN0OFST=LCD_NATIVE_WIDTH / 32+1; +#else + IO_OSD_VIDWIN0OFST=LCD_NATIVE_WIDTH / 32; +#endif + + IO_OSD_VIDWINADH=addr >> 16; + IO_OSD_VIDWIN0ADL=addr & 0xFFFF; + + IO_OSD_VIDWIN0XP=0; + IO_OSD_VIDWIN0YP=0; + + IO_OSD_VIDWIN0XL=LCD_NATIVE_WIDTH; + IO_OSD_VIDWIN0YL=LCD_NATIVE_HEIGHT; /* Set pin 36 and 35 (LCD POWER and LCD RESOLUTION) to an output */ IO_GIO_DIR2&=!(3<<3); -#if NATIVE_MAX_HEIGHT > 320 +#if LCD_NATIVE_HEIGHT > 320 /* Set LCD resolution to VGA */ IO_GIO_BITSET2=1<<3; #else /* Set LCD resolution to QVGA */ IO_GIO_BITCLR2=1<<3; #endif + + IO_OSD_OSDWINMD0|=0x01; + IO_VID_ENC_VMOD|=0x01; + + lcd_enable(true); } /* Update a fraction of the display. */ @@ -216,9 +268,10 @@ void lcd_update_rect(int x, int y, int width, int height) if (height <= 0) return; /* nothing left to do */ + src = &lcd_framebuffer[y][x]; + #if CONFIG_ORIENTATION == SCREEN_PORTRAIT dst = (fb_data *)FRAME + LCD_WIDTH*y + x; - src = &lcd_framebuffer[y][x]; /* Copy part of the Rockbox framebuffer to the second framebuffer */ if (width < LCD_WIDTH) @@ -232,21 +285,23 @@ void lcd_update_rect(int x, int y, int width, int height) lcd_copy_buffer_rect(dst, src, LCD_WIDTH*height, 1); } #else - src = &lcd_framebuffer[y][x]; - - register int xc, yc; - register fb_data *start=FRAME + LCD_HEIGHT*(LCD_WIDTH-x-1) + y + 1; + dst=FRAME + (LCD_NATIVE_WIDTH*(LCD_NATIVE_HEIGHT-1)) + - LCD_NATIVE_WIDTH*x + y ; - for(yc=0;yc> 8); cb = ((-43 * r - 85 * g + 128 * b) >> 8) + 128; + cr = ((128 * r - 107 * g - 21 * b) >> 8) + 128; + + while(IO_OSD_MISCCTL&0x08) + {}; + + /* Write in y and cb */ + IO_OSD_CLUTRAMYCB= ((unsigned char)y << 8) | (unsigned char)cb; + + /* Write in the index and cr */ + IO_OSD_CLUTRAMCR=((unsigned char)cr << 8) | i; } } #endif @@ -308,14 +437,32 @@ void lcd_blit_yuv(unsigned char * const src[3], if (!lcd_on) return; - /* y has to be at multiple of 2 or else it will mess up the HW (interleaving) */ + /* y has to be at multiple of 2 or else it will mess up the HW + * (interleaving) + */ y &= ~1; + if(y<0 || y>LCD_NATIVE_HEIGHT || x<0 || x>LCD_NATIVE_WIDTH + || height<0 || width <0) + { + return; + } + + if(y+height>LCD_NATIVE_WIDTH) + { + height=LCD_NATIVE_WIDTH-y; + } + if(x+width>LCD_NATIVE_HEIGHT) + { + width=LCD_NATIVE_HEIGHT-x; + } + /* Sorry, but width and height must be >= 2 or else */ width &= ~1; height>>=1; - fb_data *dst = (fb_data*)FRAME + LCD_WIDTH*LCD_HEIGHT - x * LCD_WIDTH + y; + fb_data * dst = FRAME + ((LCD_NATIVE_WIDTH+LCD_FUDGE)*(LCD_NATIVE_HEIGHT-1)) + - (LCD_NATIVE_WIDTH+LCD_FUDGE)*x + y ; z = stride*src_y; yuv_src[0] = src[0] + z + src_x; @@ -337,11 +484,11 @@ void lcd_blit_yuv(unsigned char * const src[3], /* This needs to be done in a block of 4 pixels */ *c_dst=*c_yuv_src[0]<<8 | *c_yuv_src[1]; *(c_dst+1)=*(c_yuv_src[0]+stride)<<8 | *c_yuv_src[2]; - c_dst-=LCD_WIDTH; + c_dst-=(LCD_NATIVE_WIDTH+LCD_FUDGE); c_yuv_src[0]++; *c_dst=*c_yuv_src[0]<<8 | *c_yuv_src[1]; *(c_dst+1)=*(c_yuv_src[0]+stride)<<8 | *c_yuv_src[2]; - c_dst-=LCD_WIDTH; + c_dst-=(LCD_NATIVE_WIDTH+LCD_FUDGE); c_yuv_src[0]++; c_yuv_src[1]++;