lcd drivers: Convert lcd_[remote_]framebuffer to a pointer
[maemo-rb.git] / firmware / target / arm / tms320dm320 / mrobe-500 / lcd-mr500.c
blobc3a96a3efd666dcc017f259fe5997ca1844d4ed6
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 "system.h"
31 #include "string-extra.h" /* memset16() */
32 #include "mmu-arm.h"
33 #include "system-target.h"
34 #include "lcd.h"
35 #include "lcd-target.h"
36 #include "dsp-target.h"
37 #include "dsp/ipc.h"
39 #if CONFIG_ORIENTATION == SCREEN_PORTRAIT
40 #define LCD_USE_DMA
41 #elif defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
42 #define LCD_USE_DMA
43 #endif
45 /* Copies a rectangle from one framebuffer to another. Can be used in
46 single transfer mode with width = num pixels, and height = 1 which
47 allows a full-width rectangle to be copied more efficiently. */
48 extern void lcd_copy_buffer_rect(fb_data *dst, const fb_data *src,
49 int width, int height);
51 #if defined(HAVE_LCD_SLEEP)
52 static bool lcd_on = true;
53 #endif
56 ** These are imported from lcd-16bit.c
58 extern unsigned fg_pattern;
59 extern unsigned bg_pattern;
61 #if defined(HAVE_LCD_SLEEP)
62 bool lcd_active(void)
64 return lcd_on;
66 #endif
68 #if defined(HAVE_LCD_SLEEP)
69 void lcd_sleep()
71 if (lcd_on)
73 lcd_on = false;
74 memset16(FRAME, 0xFFFF, LCD_WIDTH*LCD_HEIGHT);
75 sleep(HZ/5);
76 /* Disabling these saves another ~15mA */
77 bitclr16(&IO_OSD_OSDWINMD0, 0x01);
78 bitclr16(&IO_VID_ENC_VMOD, 0x01);
80 /* Disabling the LCD saves ~50mA */
81 IO_GIO_BITCLR2=1<<4; /* pin 36 */
85 void lcd_awake(void)
87 /* "enabled" implies "powered" */
88 if (!lcd_on)
90 lcd_on=true;
91 bitset16(&IO_OSD_OSDWINMD0, 0x01);
92 bitset16(&IO_VID_ENC_VMOD, 0x01);
94 sleep(2);
95 IO_GIO_BITSET2 = 1<<4;
97 lcd_update();
99 /* Wait long enough for a frame to be written */
100 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 */
111 short vidtemp = (IO_VID_ENC_VMOD & 0x7E8);
113 if(enable)
115 IO_GIO_BITSET2 = 0x80;
116 vidtemp |= 0x0003;
118 else
120 IO_GIO_BITCLR2 = 0x80;
121 vidtemp |= 0x2015;
122 IO_VID_ENC_DCLKCTL = 0x0800;
123 IO_VID_ENC_DCLKPTN0 = 0x0001;
126 IO_VID_ENC_VMOD = vidtemp;
129 /* Note this is expecting a screen size of 480x640 or 240x320, other screen
130 * sizes need to be considered for fudge factors
132 #define LCD_FUDGE LCD_NATIVE_WIDTH%32
134 /* LCD init - based on code from ingenient-bsp/bootloader/board/dm320/splash.c
135 * and code by Catalin Patulea from the M:Robe 500i linux port
137 void lcd_init_device(void)
139 unsigned int addr;
141 IO_GIO_BITCLR2 = 0x10; /* LCD off */
143 #if LCD_NATIVE_HEIGHT > 320
144 IO_GIO_BITSET2 = 1<<3; /* Set LCD resolution to VGA */
145 #else
146 IO_GIO_BITCLR2 = 1<<3; /* Set LCD resolution to QVGA */
147 #endif
149 /* Enable clocks for display */
150 bitset16(&IO_CLK_MOD1, (CLK_MOD1_VENC | CLK_MOD1_OSD));
152 /* Clear the Frame */
153 memset16(FRAME, 0x0000, LCD_WIDTH*LCD_HEIGHT);
155 IO_VID_ENC_VDCTL = 0x0;
156 IO_VID_ENC_SYNCTL = 0x0;
157 IO_VID_ENC_LCDOUT = 0x0;
159 IO_VID_ENC_VMOD = 0x4;
161 IO_VID_ENC_DCLKCTL = 0x0800;
162 IO_VID_ENC_DCLKPTN0 = 0x0001;
164 IO_OSD_OSDWINMD0 &= ~(0x0001);
165 IO_OSD_VIDWINMD &= ~(0x0001);
167 /* Setup the LCD controller */
168 IO_VID_ENC_HSPLS = 1; /* HSYNC pulse width */
169 IO_VID_ENC_VSPLS = 1; /* VSYNC pulse width */
171 /* These calculations support 640x480 and 320x240 (based on OF) */
172 IO_VID_ENC_HINT = LCD_NATIVE_WIDTH+LCD_NATIVE_WIDTH/3;
173 IO_VID_ENC_HSTART = LCD_NATIVE_WIDTH/6; /* Back porch */
174 IO_VID_ENC_HVALID = LCD_NATIVE_WIDTH; /* Data valid */
175 IO_VID_ENC_VINT = LCD_NATIVE_HEIGHT+8;
176 IO_VID_ENC_VSTART = 2;
177 IO_VID_ENC_VVALID = LCD_NATIVE_HEIGHT;
179 IO_VID_ENC_VMOD = 0x2015;
180 IO_VID_ENC_VDCTL = 0x2000;
181 IO_VID_ENC_VDPRO = 0x0000;
182 IO_VID_ENC_SYNCTL = 0x100E;
184 IO_VID_ENC_HSDLY = 0x0000;
185 IO_VID_ENC_VSDLY = 0x0000;
186 IO_VID_ENC_YCCTL = 0x0000;
187 IO_VID_ENC_RGBCTL = 0x0000;
188 IO_VID_ENC_RGBCLP = 0xFF00;
189 IO_VID_ENC_LNECTL = 0x0000;
190 IO_VID_ENC_CULLLNE = 0x0000;
191 IO_VID_ENC_LCDOUT = 0x0000;
192 IO_VID_ENC_BRTS = 0x0000;
193 IO_VID_ENC_BRTW = 0x0000;
194 IO_VID_ENC_ACCTL = 0x0000;
195 IO_VID_ENC_PWMP = 0x0000;
196 IO_VID_ENC_PWMW = 0x0000;
198 /* Setup the display */
199 IO_OSD_MODE = 0x00ff;
201 IO_OSD_ATRMD = 0x0000;
202 IO_OSD_RECTCUR = 0x0000;
204 IO_OSD_BASEPX = IO_VID_ENC_HSTART;
205 IO_OSD_BASEPY = IO_VID_ENC_VSTART;
207 addr = ((int)FRAME-CONFIG_SDRAM_START) / 32;
209 /* Setup the OSD windows */
211 /* Used for 565 RGB */
212 IO_OSD_OSDWINMD0 = 0x30C1;
214 IO_OSD_OSDWIN0OFST = LCD_NATIVE_WIDTH *2 / 32;
216 IO_OSD_OSDWINADH = addr >> 16;
217 IO_OSD_OSDWIN0ADL = addr & 0xFFFF;
219 IO_OSD_OSDWIN0XP = 0;
220 IO_OSD_OSDWIN0YP = 0;
222 /* read from OF */
223 IO_OSD_OSDWIN0XL = LCD_NATIVE_WIDTH;
224 IO_OSD_OSDWIN0YL = LCD_NATIVE_HEIGHT;
226 /* Unused */
227 IO_OSD_OSDWINMD1 = 0x10C0;
229 #if LCD_NATIVE_WIDTH%32!=0
230 IO_OSD_OSDWIN1OFST = LCD_NATIVE_WIDTH / 32+1;
231 #else
232 IO_OSD_OSDWIN1OFST = LCD_NATIVE_WIDTH / 32;
233 #endif
235 IO_OSD_OSDWIN1ADL = addr & 0xFFFF;
237 IO_OSD_OSDWIN1XP = 0;
238 IO_OSD_OSDWIN1YP = 0;
240 IO_OSD_OSDWIN1XL = LCD_NATIVE_WIDTH;
241 IO_OSD_OSDWIN1YL = LCD_NATIVE_HEIGHT;
243 IO_OSD_VIDWINMD = 0x0000;
245 addr = ((int)FRAME2-CONFIG_SDRAM_START +
246 2*(LCD_NATIVE_WIDTH*(LCD_NATIVE_HEIGHT-320)/2+
247 (LCD_NATIVE_WIDTH-240)/2))/ 32;
249 /* This is a bit messy, the LCD transfers appear to happen in chunks of 32
250 * pixels. (based on OF)
252 #if LCD_NATIVE_WIDTH%32!=0
253 IO_OSD_VIDWIN0OFST = LCD_NATIVE_WIDTH * 2 / 32+1;
254 #else
255 IO_OSD_VIDWIN0OFST = LCD_NATIVE_WIDTH * 2 / 32;
256 #endif
258 IO_OSD_VIDWINADH = addr >> 16;
259 IO_OSD_VIDWIN0ADL = addr & 0xFFFF;
261 IO_OSD_VIDWIN0XP = 0;
262 IO_OSD_VIDWIN0YP = 0;
264 IO_OSD_VIDWIN0XL = LCD_NATIVE_WIDTH;
265 IO_OSD_VIDWIN0YL = LCD_NATIVE_HEIGHT;
267 IO_OSD_OSDWINMD0 |= 0x01;
269 IO_GIO_BITSET2 = 0x10; /* LCD on */
270 // lcd_enable_composite(false);
273 #if defined(HAVE_LCD_MODES)
274 void lcd_set_mode(int mode)
276 if(mode==LCD_MODE_YUV) {
277 /* Turn off the RGB buffer and enable the YUV buffer with zoom */
278 IO_OSD_OSDWINMD0 |= 0x04;
279 IO_OSD_VIDWINMD |= 0x01;
280 #if LCD_NATIVE_WIDTH > 240
281 IO_OSD_VIDWINMD |= (0x05<<2); /* This does a 2x zoom */
282 #endif
283 memset16(FRAME2, 0x0080, LCD_NATIVE_HEIGHT*(LCD_NATIVE_WIDTH+LCD_FUDGE));
284 } else if(mode==LCD_MODE_RGB565) {
285 /* Turn on the RGB window, set it to 16 bit and turn YUV window off */
286 IO_OSD_VIDWINMD &= ~(0x01);
287 IO_OSD_OSDWIN0OFST = LCD_NATIVE_WIDTH / 16;
288 IO_OSD_OSDWINMD0 |= (1<<13);
289 IO_OSD_OSDWINMD0 &= ~0x04;
290 lcd_clear_display();
291 } else if(mode==LCD_MODE_PAL256) {
292 #if LCD_NATIVE_WIDTH%32!=0
293 IO_OSD_OSDWIN0OFST = LCD_NATIVE_WIDTH / 32+1;
294 #else
295 IO_OSD_OSDWIN0OFST = LCD_NATIVE_WIDTH / 32;
296 #endif
298 IO_OSD_VIDWINMD &= ~(0x01);
299 IO_OSD_OSDWINMD0 &= ~(1<<13);
300 IO_OSD_OSDWINMD0 |= 0x01;
303 #endif
305 #if defined(LCD_USE_DMA)
306 static void dma_start_transfer16( char *src, int src_x, int src_y, int stride,
307 int x, int y,
308 int width, int height, int pix_width)
309 __attribute__ ((section(".icode")));
310 #if CONFIG_ORIENTATION == SCREEN_PORTRAIT
311 static void dma_start_transfer16( char *src, int src_x, int src_y, int stride,
312 int x, int y,
313 int width, int height, int pix_width) {
314 char *dst;
316 /* Addresses are relative to start of SDRAM */
317 src = src + (src_y*LCD_HEIGHT + src_x) * pix_width;
318 dst = (char *)FRAME + (y * LCD_HEIGHT + x) * pix_width;
320 /* Flush the area that is being copied from. */
321 commit_dcache_range(src, (stride*pix_width*width));
323 /* Addresses are relative to start of SDRAM */
324 src -= CONFIG_SDRAM_START;
325 dst -= CONFIG_SDRAM_START;
327 /* Enable Image Buffer clock */
328 bitset16(&IO_CLK_MOD1, CLK_MOD1_IMGBUF);
330 /* ... */
331 COP_BUF_MUX1 = 0x0005;
332 /* Give the DMA access to the buffer */
333 COP_BUF_MUX0 = 0x0663;
335 /* Setup buffer offsets and transfer width/height */
336 COP_BUF_LOFST = width;
337 COP_DMA_XNUM = width;
338 COP_DMA_YNUM = 1;
340 /* ... */
341 COP_IMG_MODE = 0x0000;
343 /* Set the start address of buffer */
344 COP_BUF_ADDR = 0x0000;
346 /* Setup SDRAM stride */
347 COP_SDEM_LOFST = stride;
348 do {
349 int addr;
350 addr = (int)src;
351 addr >>= 1; /* Addresses are in 16-bit words */
353 /* Setup the registers to initiate the read from SDRAM */
354 COP_SDEM_ADDRH = addr >> 16;
355 COP_SDEM_ADDRL = addr & 0xFFFF;
357 /* Set direction and start */
358 COP_DMA_CTRL = 0x0001;
359 COP_DMA_CTRL |= 0x0003;
361 /* Wait for read to finish */
362 while(COP_DMA_CTRL & 0x02) {};
364 addr = (int)dst;
365 addr >>= 1;
367 COP_SDEM_ADDRH = addr >> 16;
368 COP_SDEM_ADDRL = addr & 0xFFFF;
370 /* Set direction and start transfer */
371 COP_DMA_CTRL = 0x0000;
372 COP_DMA_CTRL = 0x0002;
374 /* Wait for the transfer to complete */
375 while(COP_DMA_CTRL & 0x02) {};
377 /* Decrease height, update pointers/counters */
378 src += (stride*pix_width);
379 dst += (stride*pix_width);
380 height--;
381 } while(height>0);
383 /* Disable Image Buffer clock */
384 bitclr16(&IO_CLK_MOD1, CLK_MOD1_IMGBUF);
386 #else
387 static void dma_start_transfer16( char *src, int src_x, int src_y, int stride,
388 int x, int y,
389 int width, int height, int pix_width) {
390 char *dst;
392 /* Calculate starting place */
393 src = src + (src_x*LCD_HEIGHT + src_y) * pix_width;
394 dst = (char *)FRAME + (LCD_HEIGHT*(LCD_WIDTH-1) - x * LCD_HEIGHT + y)
395 * pix_width;
397 /* Flush the area that is being copied from. */
398 commit_dcache();
400 // commit_dcache_range(src, (stride*pix_width*width));
402 /* Addresses are relative to start of SDRAM */
403 src -= CONFIG_SDRAM_START;
404 dst -= CONFIG_SDRAM_START;
406 /* Enable Image Buffer clock */
407 bitset16(&IO_CLK_MOD1, CLK_MOD1_IMGBUF);
409 /* ... */
410 COP_BUF_MUX1 = 0x0005;
411 /* Give the DMA access to the buffer */
412 COP_BUF_MUX0 = 0x0663;
414 /* Setup buffer offsets and transfer width/height */
415 COP_BUF_LOFST = height;
416 COP_DMA_XNUM = height;
417 COP_DMA_YNUM = 1;
419 /* ... */
420 COP_IMG_MODE = 0x0000;
422 /* Set the start address of buffer */
423 COP_BUF_ADDR = 0x0000;
425 /* Setup SDRAM stride */
426 COP_SDEM_LOFST = stride;
427 do {
428 int addr;
429 addr = (int)src;
430 addr >>= 1; /* Addresses are in 16-bit words */
432 /* Setup the registers to initiate the read from SDRAM */
433 COP_SDEM_ADDRH = addr >> 16;
434 COP_SDEM_ADDRL = addr & 0xFFFF;
436 /* Set direction and start */
437 COP_DMA_CTRL = 0x0001;
438 COP_DMA_CTRL |= 0x0003;
440 /* Wait for read to finish */
441 while(COP_DMA_CTRL & 0x02) {};
443 addr = (int)dst;
444 addr >>= 1;
446 COP_SDEM_ADDRH = addr >> 16;
447 COP_SDEM_ADDRL = addr & 0xFFFF;
449 /* Set direction and start transfer */
450 COP_DMA_CTRL = 0x0000;
451 COP_DMA_CTRL = 0x0002;
453 /* Wait for the transfer to complete */
454 while(COP_DMA_CTRL & 0x02) {};
456 /* update the width, update pointers/counters */
457 src += (stride*pix_width);
458 dst -= (stride*pix_width);
459 width--;
460 } while(width>0);
462 /* Disable Image Buffer clock */
463 bitclr16(&IO_CLK_MOD1, CLK_MOD1_IMGBUF);
465 #endif
466 #endif
468 /* Update a fraction of the display. */
469 void lcd_update_rect(int x, int y, int width, int height)
470 __attribute__ ((section(".icode")));
471 void lcd_update_rect(int x, int y, int width, int height)
473 if (!lcd_on)
474 return;
476 if ( (width | height) < 0)
477 return; /* nothing left to do */
479 if (x + width > LCD_WIDTH)
480 width = LCD_WIDTH - x; /* Clip right */
481 if (x < 0)
482 width += x, x = 0; /* Clip left */
484 if (y + height > LCD_HEIGHT)
485 height = LCD_HEIGHT - y; /* Clip bottom */
486 if (y < 0)
487 height += y, y = 0; /* Clip top */
489 #if CONFIG_ORIENTATION == SCREEN_PORTRAIT
491 #if defined(LCD_USE_DMA)
492 dma_start_transfer16( (char *)lcd_framebuffer, x, y, LCD_WIDTH,
493 x, y, width, height, 2);
494 #else
495 register fb_data *dst;
497 dst = (fb_data *)FRAME + LCD_WIDTH*y + x;
499 /* Copy part of the Rockbox framebuffer to the second framebuffer */
500 if (width < LCD_WIDTH)
502 /* Not full width - do line-by-line */
503 lcd_copy_buffer_rect(dst, FBADDR(x,y), width, height);
505 else
507 /* Full width - copy as one line */
508 lcd_copy_buffer_rect(dst, FBADDR(x,y), LCD_WIDTH*height, 1);
510 #endif
512 #else
514 #if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
516 #if defined(LCD_USE_DMA)
517 dma_start_transfer16( (char *)lcd_framebuffer, x, y, LCD_HEIGHT,
518 x, y, width, height, 2);
519 #else
520 fb_data *src;
521 fb_data *dst;
522 src = FBADDR(0,0) + (x*LCD_HEIGHT + y);
523 dst = FRAME + (LCD_HEIGHT*(LCD_WIDTH-1) - x * LCD_HEIGHT + y);
525 while(width > 0) {
526 memcpy(src, dst, height);
527 src += LCD_HEIGHT;
528 dst -= LCD_HEIGHT;
529 width--;
531 #endif
533 #else
534 register fb_data *dst, *src;
535 src = FBADDR(x,y);
537 dst=FRAME + (LCD_NATIVE_WIDTH*(LCD_NATIVE_HEIGHT-1))
538 - LCD_NATIVE_WIDTH*x + y ;
540 height--;
541 do {
542 register int c_width=width-1;
543 register fb_data *c_dst=dst;
545 do {
546 *c_dst=*src++;
547 c_dst-=LCD_NATIVE_WIDTH;
548 } while(c_width--);
550 src+=LCD_WIDTH-width;
551 dst++;
552 } while(height--);
553 #endif
555 #endif
558 /* Update the display.
559 This must be called after all other LCD functions that change the display. */
560 void lcd_update(void) __attribute__ ((section(".icode")));
561 void lcd_update(void)
563 if (!lcd_on)
564 return;
566 lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT);
569 #if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256)
570 void lcd_blit_pal256(unsigned char *src, int src_x, int src_y, int x, int y,
571 int width, int height) __attribute__ ((section(".icode")));
572 void lcd_blit_pal256(unsigned char *src, int src_x, int src_y, int x, int y,
573 int width, int height)
575 #if CONFIG_ORIENTATION == SCREEN_PORTRAIT
576 #if defined(LCD_USE_DMA)
577 // char *dst=(char *)FRAME+x+y*(LCD_NATIVE_WIDTH+LCD_FUDGE);
579 dma_start_transfer16( src, src_x, src_y, LCD_WIDTH,
580 x, y, width, height, 1);
581 #else
582 char *dst=(char *)FRAME+x+y*(LCD_NATIVE_WIDTH+LCD_FUDGE);
584 src = src+src_x+src_y*LCD_WIDTH;
585 while(height--)
587 memcpy(dst, src, width);
589 dst = dst + ((LCD_WIDTH -x +LCD_FUDGE));
590 src = src + (LCD_WIDTH - x);
592 #endif
593 #else
594 if(width <= 0 || height <= 0)
595 return;
597 char *dst=(char *)FRAME
598 + (LCD_NATIVE_WIDTH+LCD_FUDGE)*(LCD_NATIVE_HEIGHT-1)
599 - (LCD_NATIVE_WIDTH+LCD_FUDGE)*x + y;
601 src=src+src_x+src_y*width;
605 register char *c_dst = dst;
606 register unsigned int c_width = width;
610 *c_dst = *src++;
611 c_dst -= (LCD_NATIVE_WIDTH+LCD_FUDGE);
612 } while (--c_width);
614 dst++;
615 } while(--height);
616 #endif
619 void lcd_pal256_update_pal(fb_data *palette)
621 unsigned int index = 255;
625 int y, cb, cr;
626 fb_data index_value = palette[index];
627 unsigned char r = RGB_UNPACK_RED_LCD (index_value)<<3;
628 unsigned char g = RGB_UNPACK_GREEN_LCD (index_value)<<2;
629 unsigned char b = RGB_UNPACK_BLUE_LCD (index_value)<<3;
631 y = (( 77 * r + 150 * g + 29 * b) >> 8);
632 cb = ((-43 * r - 85 * g + 128 * b) >> 8) + 128;
633 cr = ((128 * r - 107 * g - 21 * b) >> 8) + 128;
635 while(IO_OSD_MISCCTL&0x08)
638 /* Write in y and cb */
639 IO_OSD_CLUTRAMYCB= ((unsigned char)y << 8) | (unsigned char)cb;
641 /* Write in the index and cr */
642 IO_OSD_CLUTRAMCR=((unsigned char)cr << 8) | (unsigned char)index;
643 } while (index--); /* Write 256 values in */
645 #endif
647 /* Performance function to blit a YUV bitmap directly to the LCD */
648 /* Show it rotated so the LCD_WIDTH is now the height */
649 void lcd_blit_yuv(unsigned char * const src[3],
650 int src_x, int src_y, int stride,
651 int x, int y, int width, int height)
653 unsigned char const * yuv_src[3];
655 if (!lcd_on)
656 return;
658 /* y has to be on a 16 pixel boundary */
659 y &= ~0xF;
661 if( ((y | x | height | width ) < 0)
662 || y>LCD_NATIVE_HEIGHT || x>LCD_NATIVE_WIDTH )
663 return;
665 if(y+height>LCD_NATIVE_WIDTH)
667 height=LCD_NATIVE_WIDTH-y;
669 if(x+width>LCD_NATIVE_HEIGHT)
671 width=LCD_NATIVE_HEIGHT-x;
674 /* Sorry, but width and height must be >= 2 or else */
675 width &= ~1;
676 height>>=1;
678 fb_data * dst = FRAME2
679 + ((LCD_NATIVE_WIDTH+LCD_FUDGE)*(LCD_NATIVE_HEIGHT-1))
680 - (LCD_NATIVE_WIDTH+LCD_FUDGE)*x + y ;
682 /* Scope z */
684 off_t z;
685 z = stride*src_y;
686 yuv_src[0] = src[0] + z + src_x;
687 yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1);
688 yuv_src[2] = src[2] + (yuv_src[1] - src[1]);
691 int cbcr_remain=(stride>>1)-(width>>1);
692 int y_remain=(stride<<1)-width;
695 register int c_width=width;
696 register unsigned int *c_dst=(unsigned int*)dst;
699 register unsigned short Y=*((unsigned short*)yuv_src[0]);
700 register unsigned short Yst=*((unsigned short*)(yuv_src[0]+stride));
701 yuv_src[0]+=2;
703 register unsigned char Cb=*yuv_src[1]++;
704 register unsigned char Cr=*yuv_src[2]++;
706 *c_dst = (Yst<<24) | (Cr << 16) | ((Y&0xFF)<<8) | Cb;
707 *(c_dst - (LCD_NATIVE_WIDTH+LCD_FUDGE)/2) =
708 ( (Yst&0xFF00)<<16) | (Cr << 16) | (Y&0xFF00) | Cb;
710 c_dst -= (LCD_NATIVE_WIDTH+LCD_FUDGE);
712 c_width -= 2;
713 } while (c_width);
715 yuv_src[0] += y_remain; /* Skip down two luma lines-width */
716 yuv_src[1] += cbcr_remain; /* Skip down one chroma line-width/2 */
717 yuv_src[2] += cbcr_remain;
719 dst+=2;
720 } while (--height);
723 void lcd_set_contrast(int val) {
724 (void) val;
725 // TODO:
728 void lcd_set_invert_display(bool yesno) {
729 (void) yesno;
730 // TODO:
733 void lcd_set_flip(bool yesno) {
734 (void) yesno;
735 // TODO: