Move memset6() declaration to string-extra.h, kills a warning compiling for android...
[maemo-rb.git] / firmware / target / arm / tms320dm320 / mrobe-500 / lcd-mr500.c
blob838efa4cd314384a3dc2fbfddeaac89d7c49634d
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2007 by Karl Kurbjun
12 * Some of this is based on the Cowon A2 Firmware release:
13 * http://www.cowonglobal.com/download/gnu/cowon_pmp_a2_src_1.59_GPL.tar.gz
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
23 ****************************************************************************/
25 #include <sys/types.h>
26 #include "config.h"
27 #include "cpu.h"
28 #include "string.h"
29 #include "kernel.h"
30 #include "string-extra.h" /* memset16() */
31 #include "mmu-arm.h"
32 #include "system-target.h"
33 #include "lcd.h"
34 #include "lcd-target.h"
35 #include "dsp-target.h"
36 #include "dsp/ipc.h"
38 #if CONFIG_ORIENTATION == SCREEN_PORTRAIT
39 #define LCD_USE_DMA
40 #elif defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
41 #define LCD_USE_DMA
42 #endif
44 /* Copies a rectangle from one framebuffer to another. Can be used in
45 single transfer mode with width = num pixels, and height = 1 which
46 allows a full-width rectangle to be copied more efficiently. */
47 extern void lcd_copy_buffer_rect(fb_data *dst, const fb_data *src,
48 int width, int height);
50 #if defined(HAVE_LCD_SLEEP)
51 static bool lcd_on = true;
52 #endif
55 ** These are imported from lcd-16bit.c
57 extern unsigned fg_pattern;
58 extern unsigned bg_pattern;
60 #if defined(HAVE_LCD_SLEEP)
61 bool lcd_active(void)
63 return lcd_on;
65 #endif
67 #if defined(HAVE_LCD_SLEEP)
68 void lcd_sleep()
70 if (lcd_on)
72 lcd_on = false;
73 memset16(FRAME, 0xFFFF, LCD_WIDTH*LCD_HEIGHT);
74 sleep(HZ/5);
75 /* Disabling these saves another ~15mA */
76 IO_OSD_OSDWINMD0 &= ~(0x01);
77 IO_VID_ENC_VMOD &= ~(0x01);
79 /* Disabling the LCD saves ~50mA */
80 IO_GIO_BITCLR2=1<<4; /* pin 36 */
84 void lcd_awake(void)
86 /* "enabled" implies "powered" */
87 if (!lcd_on)
89 lcd_on=true;
90 IO_OSD_OSDWINMD0 |= 0x01;
91 IO_VID_ENC_VMOD |= 0x01;
93 sleep(2);
94 IO_GIO_BITSET2 = 1<<4;
96 lcd_update();
98 /* Wait long enough for a frame to be written */
99 sleep(HZ/10);
102 send_event(LCD_EVENT_ACTIVATION, NULL);
105 #endif
107 void lcd_enable_composite(bool enable)
109 /* Pin 39 appears to be related to the composite output */
110 /* 39: output, non-inverted, no-irq, falling edge, no-chat, normal */
111 dm320_set_io(39, false, false, false, false, false, 0x00);
113 short vidtemp = (IO_VID_ENC_VMOD & 0x7E8);
115 if(enable)
117 IO_GIO_BITSET2 = 0x80;
118 vidtemp |= 0x0003;
120 else
122 IO_GIO_BITCLR2 = 0x80;
123 vidtemp |= 0x2015;
124 IO_VID_ENC_DCLKCTL = 0x0800;
125 IO_VID_ENC_DCLKPTN0 = 0x0001;
128 IO_VID_ENC_VMOD = vidtemp;
131 /* Note this is expecting a screen size of 480x640 or 240x320, other screen
132 * sizes need to be considered for fudge factors
134 #define LCD_FUDGE LCD_NATIVE_WIDTH%32
136 /* LCD init - based on code from ingenient-bsp/bootloader/board/dm320/splash.c
137 * and code by Catalin Patulea from the M:Robe 500i linux port
139 void lcd_init_device(void)
141 unsigned int addr;
143 /* LCD related pins:
144 * 32 - LED above LCD
145 * 34 - R2 for 18 bit output
146 * 35 - Resolution (MO?)
147 * 36 - LCD power (INI?)
148 * 37 - Backlight and LCD power
149 * 38 - B2 for 18 bit output
152 /* Setup main LCD pins */
153 /* 32: output, non-inverted, no-irq, falling edge, no-chat, normal */
154 dm320_set_io(32, false, false, false, false, false, 0x00);
155 IO_GIO_BITCLR2 = 1; /* Turn the LED off */
157 /* 34: output, non-inverted, no-irq, falling edge, no-chat, R2 */
158 dm320_set_io(34, false, false, false, false, false, 0x02);
160 /* 35: output, non-inverted, no-irq, falling edge, no-chat, normal */
161 dm320_set_io(35, false, false, false, false, false, 0x00);
162 #if LCD_NATIVE_HEIGHT > 320
163 IO_GIO_BITSET2 = 1<<3; /* Set LCD resolution to VGA */
164 #else
165 IO_GIO_BITCLR2 = 1<<3; /* Set LCD resolution to QVGA */
166 #endif
168 /* 36: output, non-inverted, no-irq, falling edge, no-chat, normal */
169 dm320_set_io(36, false, false, false, false, false, 0x00);
170 IO_GIO_BITSET2 = 0x10; /* LCD on */
172 /* 37: output, non-inverted, no-irq, falling edge, no-chat, normal */
173 dm320_set_io(37, false, false, false, false, false, 0x00);
174 IO_GIO_BITCLR2 = (1 << 5); /* output low (backlight/lcd on) */
176 /* 38: output, non-inverted, no-irq, falling edge, no-chat, B2 */
177 dm320_set_io(38, false, false, false, false, false, 0x02);
179 /* Enable clocks for display */
180 IO_CLK_MOD1 |= (CLK_MOD1_VENC | CLK_MOD1_OSD);
182 /* Clear the Frame */
183 memset16(FRAME, 0x0000, LCD_WIDTH*LCD_HEIGHT);
185 IO_OSD_OSDWINMD0 &= ~(0x0001);
186 IO_OSD_VIDWINMD &= ~(0x0001);
188 /* Setup the LCD controller */
189 IO_VID_ENC_VMOD = 0x2014;
190 IO_VID_ENC_VDCTL = 0x2000;
191 IO_VID_ENC_VDPRO = 0x0000;
192 IO_VID_ENC_SYNCTL = 0x100E;
193 IO_VID_ENC_HSPLS = 1; /* HSYNC pulse width */
194 IO_VID_ENC_VSPLS = 1; /* VSYNC pulse width */
196 /* These calculations support 640x480 and 320x240 (based on OF) */
197 IO_VID_ENC_HINT = LCD_NATIVE_WIDTH+LCD_NATIVE_WIDTH/3;
198 IO_VID_ENC_HSTART = LCD_NATIVE_WIDTH/6; /* Back porch */
199 IO_VID_ENC_HVALID = LCD_NATIVE_WIDTH; /* Data valid */
200 IO_VID_ENC_VINT = LCD_NATIVE_HEIGHT+8;
201 IO_VID_ENC_VSTART = 2;
202 IO_VID_ENC_VVALID = LCD_NATIVE_HEIGHT;
204 IO_VID_ENC_HSDLY = 0x0000;
205 IO_VID_ENC_VSDLY = 0x0000;
206 IO_VID_ENC_YCCTL = 0x0000;
207 IO_VID_ENC_RGBCTL = 0x0000;
208 IO_VID_ENC_RGBCLP = 0xFF00;
209 IO_VID_ENC_LNECTL = 0x0000;
210 IO_VID_ENC_CULLLNE = 0x0000;
211 IO_VID_ENC_LCDOUT = 0x0000;
212 IO_VID_ENC_BRTS = 0x0000;
213 IO_VID_ENC_BRTW = 0x0000;
214 IO_VID_ENC_ACCTL = 0x0000;
215 IO_VID_ENC_PWMP = 0x0000;
216 IO_VID_ENC_PWMW = 0x0000;
218 /* Setup the display */
219 IO_OSD_MODE = 0x00ff;
221 IO_OSD_ATRMD = 0x0000;
222 IO_OSD_RECTCUR = 0x0000;
224 IO_OSD_BASEPX = IO_VID_ENC_HSTART;
225 IO_OSD_BASEPY = IO_VID_ENC_VSTART;
227 addr = ((int)FRAME-CONFIG_SDRAM_START) / 32;
229 /* Setup the OSD windows */
231 /* Used for 565 RGB */
232 IO_OSD_OSDWINMD0 = 0x30C0;
234 IO_OSD_OSDWIN0OFST = LCD_NATIVE_WIDTH *2 / 32;
236 IO_OSD_OSDWINADH = addr >> 16;
237 IO_OSD_OSDWIN0ADL = addr & 0xFFFF;
239 IO_OSD_OSDWIN0XP = 0;
240 IO_OSD_OSDWIN0YP = 0;
242 /* read from OF */
243 IO_OSD_OSDWIN0XL = LCD_NATIVE_WIDTH;
244 IO_OSD_OSDWIN0YL = LCD_NATIVE_HEIGHT;
246 /* Unused */
247 IO_OSD_OSDWINMD1 = 0x10C0;
249 #if LCD_NATIVE_WIDTH%32!=0
250 IO_OSD_OSDWIN1OFST = LCD_NATIVE_WIDTH / 32+1;
251 #else
252 IO_OSD_OSDWIN1OFST = LCD_NATIVE_WIDTH / 32;
253 #endif
255 IO_OSD_OSDWIN1ADL = addr & 0xFFFF;
257 IO_OSD_OSDWIN1XP = 0;
258 IO_OSD_OSDWIN1YP = 0;
260 IO_OSD_OSDWIN1XL = LCD_NATIVE_WIDTH;
261 IO_OSD_OSDWIN1YL = LCD_NATIVE_HEIGHT;
263 IO_OSD_VIDWINMD = 0x0000;
265 addr = ((int)FRAME2-CONFIG_SDRAM_START +
266 2*(LCD_NATIVE_WIDTH*(LCD_NATIVE_HEIGHT-320)/2+
267 (LCD_NATIVE_WIDTH-240)/2))/ 32;
269 /* This is a bit messy, the LCD transfers appear to happen in chunks of 32
270 * pixels. (based on OF)
272 #if LCD_NATIVE_WIDTH%32!=0
273 IO_OSD_VIDWIN0OFST = LCD_NATIVE_WIDTH * 2 / 32+1;
274 #else
275 IO_OSD_VIDWIN0OFST = LCD_NATIVE_WIDTH * 2 / 32;
276 #endif
278 IO_OSD_VIDWINADH = addr >> 16;
279 IO_OSD_VIDWIN0ADL = addr & 0xFFFF;
281 IO_OSD_VIDWIN0XP = 0;
282 IO_OSD_VIDWIN0YP = 0;
284 IO_OSD_VIDWIN0XL = LCD_NATIVE_WIDTH;
285 IO_OSD_VIDWIN0YL = LCD_NATIVE_HEIGHT;
287 IO_OSD_OSDWINMD0 |= 0x01;
289 lcd_enable_composite(false);
292 #if defined(HAVE_LCD_MODES)
293 void lcd_set_mode(int mode)
295 if(mode==LCD_MODE_YUV) {
296 /* Turn off the RGB buffer and enable the YUV buffer with zoom */
297 IO_OSD_OSDWINMD0 |= 0x04;
298 IO_OSD_VIDWINMD |= 0x01;
299 #if LCD_NATIVE_WIDTH > 240
300 IO_OSD_VIDWINMD |= (0x05<<2); /* This does a 2x zoom */
301 #endif
302 memset16(FRAME2, 0x0080, LCD_NATIVE_HEIGHT*(LCD_NATIVE_WIDTH+LCD_FUDGE));
303 } else if(mode==LCD_MODE_RGB565) {
304 /* Turn on the RGB window, set it to 16 bit and turn YUV window off */
305 IO_OSD_VIDWINMD &= ~(0x01);
306 IO_OSD_OSDWIN0OFST = LCD_NATIVE_WIDTH / 16;
307 IO_OSD_OSDWINMD0 |= (1<<13);
308 IO_OSD_OSDWINMD0 &= ~0x04;
309 lcd_clear_display();
310 } else if(mode==LCD_MODE_PAL256) {
311 #if LCD_NATIVE_WIDTH%32!=0
312 IO_OSD_OSDWIN0OFST = LCD_NATIVE_WIDTH / 32+1;
313 #else
314 IO_OSD_OSDWIN0OFST = LCD_NATIVE_WIDTH / 32;
315 #endif
317 IO_OSD_VIDWINMD &= ~(0x01);
318 IO_OSD_OSDWINMD0 &= ~(1<<13);
319 IO_OSD_OSDWINMD0 |= 0x01;
322 #endif
324 #if defined(LCD_USE_DMA)
325 static void dma_start_transfer16( char *src, int src_x, int src_y, int stride,
326 int x, int y,
327 int width, int height, int pix_width)
328 __attribute__ ((section(".icode")));
329 #if CONFIG_ORIENTATION == SCREEN_PORTRAIT
330 static void dma_start_transfer16( char *src, int src_x, int src_y, int stride,
331 int x, int y,
332 int width, int height, int pix_width) {
333 char *dst;
335 /* Addresses are relative to start of SDRAM */
336 src = src + (src_y*LCD_HEIGHT + src_x) * pix_width;
337 dst = (char *)FRAME + (y * LCD_HEIGHT + x) * pix_width;
339 /* Flush the area that is being copied from. */
340 clean_dcache_range(src, (stride*pix_width*width));
342 /* Addresses are relative to start of SDRAM */
343 src -= CONFIG_SDRAM_START;
344 dst -= CONFIG_SDRAM_START;
346 /* Enable Clocks */
347 IO_CLK_MOD1 |= 1<<8;
348 COP_CP_CLKC |= 0x0001;
350 /* ... */
351 COP_BUF_MUX1 = 0x0005;
352 /* Give the DMA access to the buffer */
353 COP_BUF_MUX0 = 0x0663;
355 /* Setup buffer offsets and transfer width/height */
356 COP_BUF_LOFST = width;
357 COP_DMA_XNUM = width;
358 COP_DMA_YNUM = 1;
360 /* ... */
361 COP_IMG_MODE = 0x0000;
363 /* Set the start address of buffer */
364 COP_BUF_ADDR = 0x0000;
366 /* Setup SDRAM stride */
367 COP_SDEM_LOFST = stride;
368 do {
369 int addr;
370 addr = (int)src;
371 addr >>= 1; /* Addresses are in 16-bit words */
373 /* Setup the registers to initiate the read from SDRAM */
374 COP_SDEM_ADDRH = addr >> 16;
375 COP_SDEM_ADDRL = addr & 0xFFFF;
377 /* Set direction and start */
378 COP_DMA_CTRL = 0x0001;
379 COP_DMA_CTRL |= 0x0003;
381 /* Wait for read to finish */
382 while(COP_DMA_CTRL & 0x02) {};
384 addr = (int)dst;
385 addr >>= 1;
387 COP_SDEM_ADDRH = addr >> 16;
388 COP_SDEM_ADDRL = addr & 0xFFFF;
390 /* Set direction and start transfer */
391 COP_DMA_CTRL = 0x0000;
392 COP_DMA_CTRL = 0x0002;
394 /* Wait for the transfer to complete */
395 while(COP_DMA_CTRL & 0x02) {};
397 /* Decrease height, update pointers/counters */
398 src += (stride*pix_width);
399 dst += (stride*pix_width);
400 height--;
401 } while(height>0);
403 #else
404 static void dma_start_transfer16( char *src, int src_x, int src_y, int stride,
405 int x, int y,
406 int width, int height, int pix_width) {
407 char *dst;
409 /* Calculate starting place */
410 src = src + (src_x*LCD_HEIGHT + src_y) * pix_width;
411 dst = (char *)FRAME + (LCD_HEIGHT*(LCD_WIDTH-1) - x * LCD_HEIGHT + y)
412 * pix_width;
414 /* Flush the area that is being copied from. */
415 clean_dcache_range(src, (stride*pix_width*width));
417 /* Addresses are relative to start of SDRAM */
418 src -= CONFIG_SDRAM_START;
419 dst -= CONFIG_SDRAM_START;
421 /* Enable Clocks */
422 IO_CLK_MOD1 |= 1<<8;
423 COP_CP_CLKC |= 0x0001;
425 /* ... */
426 COP_BUF_MUX1 = 0x0005;
427 /* Give the DMA access to the buffer */
428 COP_BUF_MUX0 = 0x0663;
430 /* Setup buffer offsets and transfer width/height */
431 COP_BUF_LOFST = height;
432 COP_DMA_XNUM = height;
433 COP_DMA_YNUM = 1;
435 /* ... */
436 COP_IMG_MODE = 0x0000;
438 /* Set the start address of buffer */
439 COP_BUF_ADDR = 0x0000;
441 /* Setup SDRAM stride */
442 COP_SDEM_LOFST = stride;
443 do {
444 int addr;
445 addr = (int)src;
446 addr >>= 1; /* Addresses are in 16-bit words */
448 /* Setup the registers to initiate the read from SDRAM */
449 COP_SDEM_ADDRH = addr >> 16;
450 COP_SDEM_ADDRL = addr & 0xFFFF;
452 /* Set direction and start */
453 COP_DMA_CTRL = 0x0001;
454 COP_DMA_CTRL |= 0x0003;
456 /* Wait for read to finish */
457 while(COP_DMA_CTRL & 0x02) {};
459 addr = (int)dst;
460 addr >>= 1;
462 COP_SDEM_ADDRH = addr >> 16;
463 COP_SDEM_ADDRL = addr & 0xFFFF;
465 /* Set direction and start transfer */
466 COP_DMA_CTRL = 0x0000;
467 COP_DMA_CTRL = 0x0002;
469 /* Wait for the transfer to complete */
470 while(COP_DMA_CTRL & 0x02) {};
472 /* update the width, update pointers/counters */
473 src += (stride*pix_width);
474 dst -= (stride*pix_width);
475 width--;
476 } while(width>0);
478 #endif
479 #endif
481 /* Update a fraction of the display. */
482 void lcd_update_rect(int x, int y, int width, int height)
483 __attribute__ ((section(".icode")));
484 void lcd_update_rect(int x, int y, int width, int height)
486 if (!lcd_on)
487 return;
489 if ( (width | height) < 0)
490 return; /* nothing left to do */
492 if (x + width > LCD_WIDTH)
493 width = LCD_WIDTH - x; /* Clip right */
494 if (x < 0)
495 width += x, x = 0; /* Clip left */
497 if (y + height > LCD_HEIGHT)
498 height = LCD_HEIGHT - y; /* Clip bottom */
499 if (y < 0)
500 height += y, y = 0; /* Clip top */
502 #if CONFIG_ORIENTATION == SCREEN_PORTRAIT
504 #if defined(LCD_USE_DMA)
505 dma_start_transfer16( (char *)lcd_framebuffer, x, y, LCD_WIDTH,
506 x, y, width, height, 2);
507 #else
508 register fb_data *dst;
510 dst = (fb_data *)FRAME + LCD_WIDTH*y + x;
512 /* Copy part of the Rockbox framebuffer to the second framebuffer */
513 if (width < LCD_WIDTH)
515 /* Not full width - do line-by-line */
516 lcd_copy_buffer_rect(dst, &lcd_framebuffer[y][x], width, height);
518 else
520 /* Full width - copy as one line */
521 lcd_copy_buffer_rect(dst, &lcd_framebuffer[y][x], LCD_WIDTH*height, 1);
523 #endif
525 #else
527 #if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
529 #if defined(LCD_USE_DMA)
530 dma_start_transfer16( (char *)lcd_framebuffer, x, y, LCD_HEIGHT,
531 x, y, width, height, 2);
532 #else
533 fb_data *src;
534 fb_data *dst;
535 src = &lcd_framebuffer[0][0] + (x*LCD_HEIGHT + y);
536 dst = FRAME + (LCD_HEIGHT*(LCD_WIDTH-1) - x * LCD_HEIGHT + y);
538 while(width > 0) {
539 memcpy(src, dst, height);
540 src += LCD_HEIGHT;
541 dst -= LCD_HEIGHT;
542 width--;
544 #endif
546 #else
547 register fb_data *dst, *src;
548 src = &lcd_framebuffer[y][x];
550 dst=FRAME + (LCD_NATIVE_WIDTH*(LCD_NATIVE_HEIGHT-1))
551 - LCD_NATIVE_WIDTH*x + y ;
553 height--;
554 do {
555 register int c_width=width-1;
556 register fb_data *c_dst=dst;
558 do {
559 *c_dst=*src++;
560 c_dst-=LCD_NATIVE_WIDTH;
561 } while(c_width--);
563 src+=LCD_WIDTH-width;
564 dst++;
565 } while(height--);
566 #endif
568 #endif
571 /* Update the display.
572 This must be called after all other LCD functions that change the display. */
573 void lcd_update(void) __attribute__ ((section(".icode")));
574 void lcd_update(void)
576 if (!lcd_on)
577 return;
579 lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT);
582 #if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256)
583 void lcd_blit_pal256(unsigned char *src, int src_x, int src_y, int x, int y,
584 int width, int height) __attribute__ ((section(".icode")));
585 void lcd_blit_pal256(unsigned char *src, int src_x, int src_y, int x, int y,
586 int width, int height)
588 #if CONFIG_ORIENTATION == SCREEN_PORTRAIT
589 #if defined(LCD_USE_DMA)
590 // char *dst=(char *)FRAME+x+y*(LCD_NATIVE_WIDTH+LCD_FUDGE);
592 dma_start_transfer16( src, src_x, src_y, LCD_WIDTH,
593 x, y, width, height, 1);
594 #else
595 char *dst=(char *)FRAME+x+y*(LCD_NATIVE_WIDTH+LCD_FUDGE);
597 src = src+src_x+src_y*LCD_WIDTH;
598 while(height--)
600 memcpy(dst, src, width);
602 dst = dst + ((LCD_WIDTH -x +LCD_FUDGE));
603 src = src + (LCD_WIDTH - x);
605 #endif
606 #else
607 char *dst=(char *)FRAME
608 + (LCD_NATIVE_WIDTH+LCD_FUDGE)*(LCD_NATIVE_HEIGHT-1)
609 - (LCD_NATIVE_WIDTH+LCD_FUDGE)*x + y;
611 src=src+src_x+src_y*width;
613 while(height--)
615 register char *c_src=src;
616 register char *c_dst=dst;
617 register int c_width=width;
619 while (c_width--)
621 *c_dst = *c_src++;
622 c_dst -= (LCD_NATIVE_WIDTH+LCD_FUDGE);
625 dst++;
626 src+=width;
628 #endif
631 void lcd_pal256_update_pal(fb_data *palette)
633 unsigned char i;
634 for(i=0; i< 255; i++)
636 int y, cb, cr;
637 unsigned char r=RGB_UNPACK_RED_LCD(palette[i])<<3;
638 unsigned char g=RGB_UNPACK_GREEN_LCD(palette[i])<<2;
639 unsigned char b=RGB_UNPACK_BLUE_LCD(palette[i])<<3;
641 y = ((77 * r + 150 * g + 29 * b) >> 8); cb = ((-43 * r - 85 * g + 128 * b) >> 8) + 128;
642 cr = ((128 * r - 107 * g - 21 * b) >> 8) + 128;
644 while(IO_OSD_MISCCTL&0x08)
647 /* Write in y and cb */
648 IO_OSD_CLUTRAMYCB= ((unsigned char)y << 8) | (unsigned char)cb;
650 /* Write in the index and cr */
651 IO_OSD_CLUTRAMCR=((unsigned char)cr << 8) | i;
654 #endif
656 /* Performance function to blit a YUV bitmap directly to the LCD */
657 /* Show it rotated so the LCD_WIDTH is now the height */
658 void lcd_blit_yuv(unsigned char * const src[3],
659 int src_x, int src_y, int stride,
660 int x, int y, int width, int height)
662 unsigned char const * yuv_src[3];
664 if (!lcd_on)
665 return;
667 /* y has to be on a 16 pixel boundary */
668 y &= ~0xF;
670 if( ((y | x | height | width ) < 0)
671 || y>LCD_NATIVE_HEIGHT || x>LCD_NATIVE_WIDTH )
672 return;
674 if(y+height>LCD_NATIVE_WIDTH)
676 height=LCD_NATIVE_WIDTH-y;
678 if(x+width>LCD_NATIVE_HEIGHT)
680 width=LCD_NATIVE_HEIGHT-x;
683 /* Sorry, but width and height must be >= 2 or else */
684 width &= ~1;
685 height>>=1;
687 fb_data * dst = FRAME2
688 + ((LCD_NATIVE_WIDTH+LCD_FUDGE)*(LCD_NATIVE_HEIGHT-1))
689 - (LCD_NATIVE_WIDTH+LCD_FUDGE)*x + y ;
691 /* Scope z */
693 off_t z;
694 z = stride*src_y;
695 yuv_src[0] = src[0] + z + src_x;
696 yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1);
697 yuv_src[2] = src[2] + (yuv_src[1] - src[1]);
700 int cbcr_remain=(stride>>1)-(width>>1);
701 int y_remain=(stride<<1)-width;
704 register int c_width=width;
705 register unsigned int *c_dst=(unsigned int*)dst;
708 register unsigned short Y=*((unsigned short*)yuv_src[0]);
709 register unsigned short Yst=*((unsigned short*)(yuv_src[0]+stride));
710 yuv_src[0]+=2;
712 register unsigned char Cb=*yuv_src[1]++;
713 register unsigned char Cr=*yuv_src[2]++;
715 *c_dst = (Yst<<24) | (Cr << 16) | ((Y&0xFF)<<8) | Cb;
716 *(c_dst - (LCD_NATIVE_WIDTH+LCD_FUDGE)/2) =
717 ( (Yst&0xFF00)<<16) | (Cr << 16) | (Y&0xFF00) | Cb;
719 c_dst -= (LCD_NATIVE_WIDTH+LCD_FUDGE);
721 c_width -= 2;
723 while (c_width > 0);
725 yuv_src[0] += y_remain; /* Skip down two luma lines-width */
726 yuv_src[1] += cbcr_remain; /* Skip down one chroma line-width/2 */
727 yuv_src[2] += cbcr_remain;
729 dst+=2;
731 while (--height > 0);
734 void lcd_set_contrast(int val) {
735 (void) val;
736 // TODO:
739 void lcd_set_invert_display(bool yesno) {
740 (void) yesno;
741 // TODO:
744 void lcd_set_flip(bool yesno) {
745 (void) yesno;
746 // TODO: