blob: 1cd59397a6a40030b78bea2d81366a46dbf9381d [file] [log] [blame]
Karl Kurbjun7b97fe22007-09-20 04:46:41 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
Karl Kurbjunbebbac82007-09-22 15:43:38 +00008 * $Id$
Karl Kurbjun7b97fe22007-09-20 04:46:41 +00009 *
10 * Copyright (C) 2007 by Karl Kurbjun
11 *
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
14 *
15 * All files in this archive are subject to the GNU General Public License.
16 * See the file COPYING in the source tree root for full license agreement.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22
23#include "config.h"
24#include "cpu.h"
25#include "string.h"
26#include "lcd.h"
27#include "kernel.h"
28#include "memory.h"
29#include "system-target.h"
30
Karl Kurbjunfdbc01c2007-10-21 23:12:17 +000031/* Copies a rectangle from one framebuffer to another. Can be used in
32 single transfer mode with width = num pixels, and height = 1 which
33 allows a full-width rectangle to be copied more efficiently. */
34extern void lcd_copy_buffer_rect(fb_data *dst, const fb_data *src,
35 int width, int height);
36
Karl Kurbjun7b97fe22007-09-20 04:46:41 +000037static volatile bool lcd_on = true;
38volatile bool lcd_poweroff = false;
39/*
40** These are imported from lcd-16bit.c
41*/
42extern unsigned fg_pattern;
43extern unsigned bg_pattern;
44
45bool lcd_enabled(void)
46{
47 return lcd_on;
48}
49
50/* LCD init - based on code from ingenient-bsp/bootloader/board/dm320/splash.c
51 * and code by Catalin Patulea from the M:Robe 500i linux port
52 */
53void lcd_init_device(void)
54{
55 unsigned int addr;
56
57 /* Clear the Frame */
58 memset16(FRAME, 0x0000, LCD_WIDTH*LCD_HEIGHT);
59
60 outw(0x00ff, IO_OSD_MODE);
61 outw(0x0002, IO_OSD_VIDWINMD);
62 outw(0x2001, IO_OSD_OSDWINMD0);
63 outw(0x0002, IO_OSD_OSDWINMD1);
64 outw(0x0000, IO_OSD_ATRMD);
65 outw(0x0000, IO_OSD_RECTCUR);
66
67 outw((480*2) / 32, IO_OSD_OSDWIN0OFST);
68 addr = ((int)FRAME-CONFIG_SDRAM_START) / 32;
69 outw(addr >> 16, IO_OSD_OSDWINADH);
70 outw(addr & 0xFFFF, IO_OSD_OSDWIN0ADL);
71
72 outw(80, IO_OSD_BASEPX);
73 outw(2, IO_OSD_BASEPY);
74
75 outw(0, IO_OSD_OSDWIN0XP);
76 outw(0, IO_OSD_OSDWIN0YP);
77 outw(480, IO_OSD_OSDWIN0XL);
78 outw(640, IO_OSD_OSDWIN0YL);
79}
80
81/* Update a fraction of the display. */
82void lcd_update_rect(int x, int y, int width, int height)
83{
84 fb_data *dst, *src;
85
86 if (!lcd_on)
87 return;
88
89 if (x + width > LCD_WIDTH)
90 width = LCD_WIDTH - x; /* Clip right */
91 if (x < 0)
92 width += x, x = 0; /* Clip left */
93 if (width <= 0)
94 return; /* nothing left to do */
95
96 if (y + height > LCD_HEIGHT)
97 height = LCD_HEIGHT - y; /* Clip bottom */
98 if (y < 0)
99 height += y, y = 0; /* Clip top */
100 if (height <= 0)
101 return; /* nothing left to do */
102
Jonathan Gordon28dfb542007-11-11 04:48:33 +0000103#if CONFIG_ORIENTATION == SCREEN_PORTAIT
Karl Kurbjun7b97fe22007-09-20 04:46:41 +0000104 dst = (fb_data *)FRAME + LCD_WIDTH*y + x;
105 src = &lcd_framebuffer[y][x];
106
107 /* Copy part of the Rockbox framebuffer to the second framebuffer */
108 if (width < LCD_WIDTH)
109 {
Karl Kurbjun7b97fe22007-09-20 04:46:41 +0000110 /* Not full width - do line-by-line */
Karl Kurbjunfdbc01c2007-10-21 23:12:17 +0000111 lcd_copy_buffer_rect(dst, src, width, height);
Karl Kurbjun7b97fe22007-09-20 04:46:41 +0000112 }
113 else
114 {
115 /* Full width - copy as one line */
Karl Kurbjunfdbc01c2007-10-21 23:12:17 +0000116 lcd_copy_buffer_rect(dst, src, LCD_WIDTH*height, 1);
Karl Kurbjun7b97fe22007-09-20 04:46:41 +0000117 }
Karl Kurbjun38548c72007-11-02 05:21:34 +0000118#else
119
120#if 0
121 src = &lcd_framebuffer[y][x];
122
123 register int xc, yc;
124 register fb_data *start=(fb_data *)FRAME + (LCD_HEIGHT-x)*LCD_WIDTH + y;
125
126 for(yc=0;yc<height;yc++)
127 {
128 dst=start+yc;
129 for(xc=0; xc<width; xc++)
130 {
131 *dst=*src++;
132 dst-=LCD_HEIGHT;
133 }
134 }
135#else
136 lcd_update();
137#endif
138#endif
Karl Kurbjun7b97fe22007-09-20 04:46:41 +0000139}
140
141void lcd_enable(bool state)
142{
143 (void)state;
144}
145
146/* Update the display.
147 This must be called after all other LCD functions that change the display. */
148void lcd_update(void)
149{
150 if (!lcd_on)
151 return;
Jonathan Gordon28dfb542007-11-11 04:48:33 +0000152#if CONFIG_ORIENTATION == SCREEN_PORTAIT
Karl Kurbjunfdbc01c2007-10-21 23:12:17 +0000153 lcd_copy_buffer_rect((fb_data *)FRAME, &lcd_framebuffer[0][0],
154 LCD_WIDTH*LCD_HEIGHT, 1);
155#else
156 register fb_data *dst, *src=&lcd_framebuffer[0][0];
157 register unsigned int x, y;
158
Karl Kurbjun38548c72007-11-02 05:21:34 +0000159 register fb_data *start=FRAME + LCD_HEIGHT*(LCD_WIDTH-1)+1;
Karl Kurbjun7b97fe22007-09-20 04:46:41 +0000160
Karl Kurbjunfdbc01c2007-10-21 23:12:17 +0000161 for(y=0; y<LCD_HEIGHT;y++)
162 {
163 dst=start+y;
164 for(x=0; x<LCD_WIDTH; x++)
165 {
166 *dst=*src++;
167 dst-=LCD_HEIGHT;
168 }
169 }
170#endif
Karl Kurbjun7b97fe22007-09-20 04:46:41 +0000171}
172
173/* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */
174extern void lcd_write_yuv420_lines(fb_data *dst,
175 unsigned char chroma_buf[LCD_HEIGHT/2*3],
176 unsigned char const * const src[3],
177 int width,
178 int stride);
179/* Performance function to blit a YUV bitmap directly to the LCD */
180/* For the Gigabeat - show it rotated */
181/* So the LCD_WIDTH is now the height */
182void lcd_yuv_blit(unsigned char * const src[3],
183 int src_x, int src_y, int stride,
184 int x, int y, int width, int height)
185{
186 /* Caches for chroma data so it only need be recaculated every other
187 line */
Karl Kurbjunb7a4e102007-10-13 14:53:34 +0000188/* unsigned char chroma_buf[LCD_HEIGHT/2*3];*/ /* 480 bytes */
Karl Kurbjun7b97fe22007-09-20 04:46:41 +0000189 unsigned char const * yuv_src[3];
190 off_t z;
191
192 if (!lcd_on)
193 return;
194
195 /* Sorry, but width and height must be >= 2 or else */
196 width &= ~1;
197 height >>= 1;
198
199 fb_data *dst = (fb_data*)FRAME + x * LCD_WIDTH + (LCD_WIDTH - y) - 1;
200
201 z = stride*src_y;
202 yuv_src[0] = src[0] + z + src_x;
203 yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1);
204 yuv_src[2] = src[2] + (yuv_src[1] - src[1]);
205
206 do
207 {
Karl Kurbjuna56b6532007-09-30 16:29:21 +0000208/* lcd_write_yuv420_lines(dst, chroma_buf, yuv_src, width,
Karl Kurbjun7b97fe22007-09-20 04:46:41 +0000209 stride);
Karl Kurbjuna56b6532007-09-30 16:29:21 +0000210 */
Karl Kurbjun7b97fe22007-09-20 04:46:41 +0000211 yuv_src[0] += stride << 1; /* Skip down two luma lines */
212 yuv_src[1] += stride >> 1; /* Skip down one chroma line */
213 yuv_src[2] += stride >> 1;
214 dst -= 2;
215 }
216 while (--height > 0);
217}
218
219void lcd_set_contrast(int val) {
220 (void) val;
221 // TODO:
222}
223
224void lcd_set_invert_display(bool yesno) {
225 (void) yesno;
226 // TODO:
227}
228
229void lcd_blit(const fb_data* data, int bx, int y, int bwidth,
230 int height, int stride)
231{
232 (void) data;
233 (void) bx;
234 (void) y;
235 (void) bwidth;
236 (void) height;
237 (void) stride;
238 //TODO:
239}
240
241void lcd_set_flip(bool yesno) {
242 (void) yesno;
243 // TODO:
244}
245