blob: e4b36eb9be8b6cc1a18076342ae26ec2d693b6e5 [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"
Karl Kurbjun95ef8592007-11-20 04:55:57 +000030#include "lcd-target.h"
Karl Kurbjun7b97fe22007-09-20 04:46:41 +000031
Karl Kurbjunfdbc01c2007-10-21 23:12:17 +000032/* Copies a rectangle from one framebuffer to another. Can be used in
33 single transfer mode with width = num pixels, and height = 1 which
34 allows a full-width rectangle to be copied more efficiently. */
35extern void lcd_copy_buffer_rect(fb_data *dst, const fb_data *src,
36 int width, int height);
37
Karl Kurbjun7b97fe22007-09-20 04:46:41 +000038static volatile bool lcd_on = true;
39volatile bool lcd_poweroff = false;
40/*
41** These are imported from lcd-16bit.c
42*/
43extern unsigned fg_pattern;
44extern unsigned bg_pattern;
45
46bool lcd_enabled(void)
47{
48 return lcd_on;
49}
50
51/* LCD init - based on code from ingenient-bsp/bootloader/board/dm320/splash.c
52 * and code by Catalin Patulea from the M:Robe 500i linux port
53 */
54void lcd_init_device(void)
55{
56 unsigned int addr;
57
58 /* Clear the Frame */
59 memset16(FRAME, 0x0000, LCD_WIDTH*LCD_HEIGHT);
60
Karl Kurbjun95ef8592007-11-20 04:55:57 +000061 IO_OSD_MODE=0x00ff;
62 IO_OSD_VIDWINMD=0x0002;
63 IO_OSD_OSDWINMD0=0x2001;
64 IO_OSD_OSDWINMD1=0x0002;
65 IO_OSD_ATRMD=0x0000;
66 IO_OSD_RECTCUR=0x0000;
Karl Kurbjun7b97fe22007-09-20 04:46:41 +000067
Karl Kurbjun95ef8592007-11-20 04:55:57 +000068 IO_OSD_OSDWIN0OFST=(480*2) / 32;
Karl Kurbjun7b97fe22007-09-20 04:46:41 +000069 addr = ((int)FRAME-CONFIG_SDRAM_START) / 32;
Karl Kurbjun95ef8592007-11-20 04:55:57 +000070 IO_OSD_OSDWINADH=addr >> 16;
71 IO_OSD_OSDWIN0ADL=addr & 0xFFFF;
Karl Kurbjun7b97fe22007-09-20 04:46:41 +000072
Karl Kurbjun95ef8592007-11-20 04:55:57 +000073 IO_OSD_BASEPX=80;
74 IO_OSD_BASEPY=2;
Karl Kurbjun7b97fe22007-09-20 04:46:41 +000075
Karl Kurbjun95ef8592007-11-20 04:55:57 +000076 IO_OSD_OSDWIN0XP=0;
77 IO_OSD_OSDWIN0YP=0;
78 IO_OSD_OSDWIN0XL=480;
79 IO_OSD_OSDWIN0YL=640;
Karl Kurbjun7b97fe22007-09-20 04:46:41 +000080}
81
82/* Update a fraction of the display. */
83void lcd_update_rect(int x, int y, int width, int height)
84{
Karl Kurbjuna8c02022007-11-19 06:26:53 +000085 register fb_data *dst, *src;
Karl Kurbjun7b97fe22007-09-20 04:46:41 +000086
87 if (!lcd_on)
88 return;
89
90 if (x + width > LCD_WIDTH)
91 width = LCD_WIDTH - x; /* Clip right */
92 if (x < 0)
93 width += x, x = 0; /* Clip left */
94 if (width <= 0)
95 return; /* nothing left to do */
96
97 if (y + height > LCD_HEIGHT)
98 height = LCD_HEIGHT - y; /* Clip bottom */
99 if (y < 0)
100 height += y, y = 0; /* Clip top */
101 if (height <= 0)
102 return; /* nothing left to do */
103
Jonathan Gordon28dfb542007-11-11 04:48:33 +0000104#if CONFIG_ORIENTATION == SCREEN_PORTAIT
Karl Kurbjun7b97fe22007-09-20 04:46:41 +0000105 dst = (fb_data *)FRAME + LCD_WIDTH*y + x;
106 src = &lcd_framebuffer[y][x];
107
108 /* Copy part of the Rockbox framebuffer to the second framebuffer */
109 if (width < LCD_WIDTH)
110 {
Karl Kurbjun7b97fe22007-09-20 04:46:41 +0000111 /* Not full width - do line-by-line */
Karl Kurbjunfdbc01c2007-10-21 23:12:17 +0000112 lcd_copy_buffer_rect(dst, src, width, height);
Karl Kurbjun7b97fe22007-09-20 04:46:41 +0000113 }
114 else
115 {
116 /* Full width - copy as one line */
Karl Kurbjunfdbc01c2007-10-21 23:12:17 +0000117 lcd_copy_buffer_rect(dst, src, LCD_WIDTH*height, 1);
Karl Kurbjun7b97fe22007-09-20 04:46:41 +0000118 }
Karl Kurbjun38548c72007-11-02 05:21:34 +0000119#else
Karl Kurbjun38548c72007-11-02 05:21:34 +0000120 src = &lcd_framebuffer[y][x];
121
122 register int xc, yc;
Karl Kurbjuna8c02022007-11-19 06:26:53 +0000123 register fb_data *start=FRAME + LCD_HEIGHT*(LCD_WIDTH-x-1) + y + 1;
Karl Kurbjun38548c72007-11-02 05:21:34 +0000124
125 for(yc=0;yc<height;yc++)
126 {
127 dst=start+yc;
128 for(xc=0; xc<width; xc++)
129 {
130 *dst=*src++;
131 dst-=LCD_HEIGHT;
132 }
Karl Kurbjuna8c02022007-11-19 06:26:53 +0000133 src+=x;
Karl Kurbjun38548c72007-11-02 05:21:34 +0000134 }
Karl Kurbjun38548c72007-11-02 05:21:34 +0000135#endif
Karl Kurbjun7b97fe22007-09-20 04:46:41 +0000136}
137
138void lcd_enable(bool state)
139{
140 (void)state;
141}
142
143/* Update the display.
144 This must be called after all other LCD functions that change the display. */
145void lcd_update(void)
146{
147 if (!lcd_on)
148 return;
Jonathan Gordon28dfb542007-11-11 04:48:33 +0000149#if CONFIG_ORIENTATION == SCREEN_PORTAIT
Karl Kurbjunfdbc01c2007-10-21 23:12:17 +0000150 lcd_copy_buffer_rect((fb_data *)FRAME, &lcd_framebuffer[0][0],
151 LCD_WIDTH*LCD_HEIGHT, 1);
152#else
Karl Kurbjuna8c02022007-11-19 06:26:53 +0000153 lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT);
Karl Kurbjunfdbc01c2007-10-21 23:12:17 +0000154#endif
Karl Kurbjun7b97fe22007-09-20 04:46:41 +0000155}
156
157/* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */
158extern void lcd_write_yuv420_lines(fb_data *dst,
159 unsigned char chroma_buf[LCD_HEIGHT/2*3],
160 unsigned char const * const src[3],
161 int width,
162 int stride);
163/* Performance function to blit a YUV bitmap directly to the LCD */
164/* For the Gigabeat - show it rotated */
165/* So the LCD_WIDTH is now the height */
166void lcd_yuv_blit(unsigned char * const src[3],
167 int src_x, int src_y, int stride,
168 int x, int y, int width, int height)
169{
170 /* Caches for chroma data so it only need be recaculated every other
171 line */
Karl Kurbjun95ef8592007-11-20 04:55:57 +0000172 unsigned char chroma_buf[LCD_HEIGHT/2*3]; /* 480 bytes */
Karl Kurbjun7b97fe22007-09-20 04:46:41 +0000173 unsigned char const * yuv_src[3];
174 off_t z;
175
176 if (!lcd_on)
177 return;
178
179 /* Sorry, but width and height must be >= 2 or else */
180 width &= ~1;
181 height >>= 1;
182
183 fb_data *dst = (fb_data*)FRAME + x * LCD_WIDTH + (LCD_WIDTH - y) - 1;
184
185 z = stride*src_y;
186 yuv_src[0] = src[0] + z + src_x;
187 yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1);
188 yuv_src[2] = src[2] + (yuv_src[1] - src[1]);
189
190 do
191 {
Karl Kurbjun95ef8592007-11-20 04:55:57 +0000192 lcd_write_yuv420_lines(dst, chroma_buf, yuv_src, width,
Karl Kurbjun7b97fe22007-09-20 04:46:41 +0000193 stride);
Karl Kurbjun95ef8592007-11-20 04:55:57 +0000194
Karl Kurbjun7b97fe22007-09-20 04:46:41 +0000195 yuv_src[0] += stride << 1; /* Skip down two luma lines */
196 yuv_src[1] += stride >> 1; /* Skip down one chroma line */
197 yuv_src[2] += stride >> 1;
198 dst -= 2;
199 }
200 while (--height > 0);
201}
202
203void lcd_set_contrast(int val) {
204 (void) val;
205 // TODO:
206}
207
208void lcd_set_invert_display(bool yesno) {
209 (void) yesno;
210 // TODO:
211}
212
213void lcd_blit(const fb_data* data, int bx, int y, int bwidth,
214 int height, int stride)
215{
216 (void) data;
217 (void) bx;
218 (void) y;
219 (void) bwidth;
220 (void) height;
221 (void) stride;
222 //TODO:
223}
224
225void lcd_set_flip(bool yesno) {
226 (void) yesno;
227 // TODO:
228}
229