summaryrefslogtreecommitdiff
path: root/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c
diff options
context:
space:
mode:
authorMarcoen Hirschberg <marcoen@gmail.com>2007-04-18 12:22:27 +0000
committerMarcoen Hirschberg <marcoen@gmail.com>2007-04-18 12:22:27 +0000
commitf44f961812c059b69df19ac5bd828986ba10513f (patch)
tree9b19de69126ed041992f31a7c690db841a36af6f /firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c
parentc3dcc87aa494934943769b70fd752af1271d196a (diff)
downloadrockbox-f44f961812c059b69df19ac5bd828986ba10513f.tar.gz
rockbox-f44f961812c059b69df19ac5bd828986ba10513f.zip
move the Gigabeat from gigabeat/meg-fx to s3c2440/gigabeat-fx to avoid problems with possible ports in the future: Gigabeat S/V (i.mx31 based) and Kenwood HD20GA7/HD20GA9 (s3c2440 based)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13200 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c')
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c367
1 files changed, 367 insertions, 0 deletions
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c
new file mode 100644
index 0000000000..1bb68f9686
--- /dev/null
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c
@@ -0,0 +1,367 @@
1#include "config.h"
2#include <string.h>
3#include "cpu.h"
4#include "lcd.h"
5#include "kernel.h"
6#include "system.h"
7#include "mmu-meg-fx.h"
8#include <stdlib.h>
9#include "memory.h"
10#include "lcd-target.h"
11#include "font.h"
12#include "rbunicode.h"
13#include "bidi.h"
14
15#define LCDADDR(x, y) (&lcd_framebuffer[(y)][(x)])
16/*
17** We prepare foreground and background fills ahead of time - DMA fills in 16 byte groups
18*/
19unsigned long fg_pattern_blit[4];
20unsigned long bg_pattern_blit[4];
21
22volatile bool use_dma_blit = false;
23static volatile bool lcd_on = true;
24volatile bool lcd_poweroff = false;
25/*
26** These are imported from lcd-16bit.c
27*/
28extern unsigned fg_pattern;
29extern unsigned bg_pattern;
30
31bool lcd_enabled()
32{
33 return lcd_on;
34}
35
36unsigned int LCDBANK(unsigned int address)
37{
38 return ((address >> 22) & 0xff);
39}
40
41unsigned int LCDBASEU(unsigned int address)
42{
43 return (address & ((1 << 22)-1)) >> 1;
44}
45
46unsigned int LCDBASEL(unsigned int address)
47{
48 address += 320*240*2;
49 return (address & ((1 << 22)-1)) >> 1;
50}
51
52
53/* LCD init */
54void lcd_init_device(void)
55{
56 LCDSADDR1 = (LCDBANK((unsigned)FRAME) << 21) | (LCDBASEU((unsigned)FRAME));
57 LCDSADDR2 = LCDBASEL((unsigned)FRAME);
58 LCDSADDR3 = 0x000000F0;
59
60 LCDCON5 |= 1 << 11; /* Switch from 555I mode to 565 mode */
61
62#if !defined(BOOTLOADER)
63 memset16(fg_pattern_blit, fg_pattern, sizeof(fg_pattern_blit)/2);
64 memset16(bg_pattern_blit, bg_pattern, sizeof(bg_pattern_blit)/2);
65 clean_dcache_range((void *)fg_pattern_blit, sizeof(fg_pattern_blit));
66 clean_dcache_range((void *)bg_pattern_blit, sizeof(bg_pattern_blit));
67 use_dma_blit = true;
68 lcd_poweroff = false;
69#endif
70}
71
72/* Update a fraction of the display. */
73void lcd_update_rect(int x, int y, int width, int height)
74{
75 (void)x;
76 (void)width;
77 (void)y;
78 (void)height;
79
80 if(!lcd_on)
81 {
82 sleep(200);
83 return;
84 }
85 if (use_dma_blit)
86 {
87 /* Wait for this controller to stop pending transfer */
88 while((DSTAT1 & 0x000fffff))
89 CLKCON |= (1 << 2); /* set IDLE bit */
90
91 /* Flush DCache */
92 invalidate_dcache_range((void *)(((int) &lcd_framebuffer[0][0])+(y * sizeof(fb_data) * LCD_WIDTH)), (height * sizeof(fb_data) * LCD_WIDTH));
93
94 /* set DMA dest */
95 DIDST1 = ((int) FRAME) + (y * sizeof(fb_data) * LCD_WIDTH);
96
97 /* FRAME on AHB buf, increment */
98 DIDSTC1 = 0;
99 /* Handshake on AHB, Burst transfer, Whole service, Don't reload, transfer 32-bits */
100 DCON1 = ((1<<30) | (1<<28) | (1<<27) | (1<<22) | (2<<20)) | ((height * sizeof(fb_data) * LCD_WIDTH) >> 4);
101
102 /* set DMA source */
103 DISRC1 = ((int) &lcd_framebuffer[0][0]) + (y * sizeof(fb_data) * LCD_WIDTH) + 0x30000000;
104 /* memory is on AHB bus, increment addresses */
105 DISRCC1 = 0x00;
106
107 /* Activate the channel */
108 DMASKTRIG1 = 0x2;
109
110 /* Start DMA */
111 DMASKTRIG1 |= 0x1;
112
113 /* Wait for transfer to complete */
114 while((DSTAT1 & 0x000fffff))
115 CLKCON |= (1 << 2); /* set IDLE bit */
116 }
117 else
118 memcpy(((char*)FRAME) + (y * sizeof(fb_data) * LCD_WIDTH), ((char *)&lcd_framebuffer) + (y * sizeof(fb_data) * LCD_WIDTH), ((height * sizeof(fb_data) * LCD_WIDTH)));
119}
120
121
122void lcd_enable(bool state)
123{
124 if(!lcd_poweroff)
125 return;
126 if(state) {
127 if(!lcd_on) {
128 lcd_on = true;
129 memcpy(FRAME, lcd_framebuffer, LCD_WIDTH*LCD_HEIGHT*2);
130 LCDCON1 |= 1;
131 }
132 }
133 else {
134 if(lcd_on) {
135 lcd_on = false;
136 LCDCON1 &= ~1;
137 }
138 }
139}
140
141void lcd_set_foreground(unsigned color)
142{
143 fg_pattern = color;
144
145 memset16(fg_pattern_blit, fg_pattern, sizeof(fg_pattern_blit)/2);
146 invalidate_dcache_range((void *)fg_pattern_blit, sizeof(fg_pattern_blit));
147}
148
149void lcd_set_background(unsigned color)
150{
151 bg_pattern = color;
152 memset16(bg_pattern_blit, bg_pattern, sizeof(bg_pattern_blit)/2);
153 invalidate_dcache_range((void *)bg_pattern_blit, sizeof(bg_pattern_blit));
154}
155
156void lcd_device_prepare_backdrop(fb_data* backdrop)
157{
158 if(backdrop)
159 invalidate_dcache_range((void *)backdrop, (LCD_HEIGHT * sizeof(fb_data) * LCD_WIDTH));
160}
161
162void lcd_clear_display_dma(void)
163{
164 void *src;
165 bool inc = false;
166
167 if(!lcd_on) {
168 sleep(200);
169 }
170 if (lcd_get_drawmode() & DRMODE_INVERSEVID)
171 src = fg_pattern_blit;
172 else
173 {
174 fb_data* lcd_backdrop = lcd_get_backdrop();
175
176 if (!lcd_backdrop)
177 src = bg_pattern_blit;
178 else
179 {
180 src = lcd_backdrop;
181 inc = true;
182 }
183 }
184 /* Wait for any pending transfer to complete */
185 while((DSTAT3 & 0x000fffff))
186 CLKCON |= (1 << 2); /* set IDLE bit */
187 DMASKTRIG3 |= 0x4; /* Stop controller */
188 DIDST3 = ((int) &lcd_framebuffer[0][0]) + 0x30000000; /* set DMA dest, physical address */
189 DIDSTC3 = 0; /* Dest on AHB, increment */
190
191 DISRC3 = ((int) src) + 0x30000000; /* Set source, in physical space */
192 DISRCC3 = inc ? 0x00 : 0x01; /* memory is on AHB bus, increment addresses based on backdrop */
193
194 /* Handshake on AHB, Burst mode, whole service mode, no reload, move 32-bits */
195 DCON3 = ((1<<30) | (1<<28) | (1<<27) | (1<<22) | (2<<20)) | ((LCD_WIDTH*LCD_HEIGHT*sizeof(fb_data)) >> 4);
196
197 /* Dump DCache for dest, we are about to overwrite it with DMA */
198 invalidate_dcache_range((void *)lcd_framebuffer, sizeof(lcd_framebuffer));
199 /* Activate the channel */
200 DMASKTRIG3 = 2;
201 /* Start DMA */
202 DMASKTRIG3 |= 1;
203
204 /* Wait for transfer to complete */
205 while((DSTAT3 & 0x000fffff))
206 CLKCON |= (1 << 2); /* set IDLE bit */
207}
208
209void lcd_clear_display(void)
210{
211 lcd_stop_scroll();
212
213 if(use_dma_blit)
214 {
215 lcd_clear_display_dma();
216 return;
217 }
218
219 fb_data *dst = &lcd_framebuffer[0][0];
220
221 if (lcd_get_drawmode() & DRMODE_INVERSEVID)
222 {
223 memset16(dst, fg_pattern, LCD_WIDTH*LCD_HEIGHT);
224 }
225 else
226 {
227 fb_data* lcd_backdrop = lcd_get_backdrop();
228 if (!lcd_backdrop)
229 memset16(dst, bg_pattern, LCD_WIDTH*LCD_HEIGHT);
230 else
231 memcpy(dst, lcd_backdrop, sizeof(lcd_framebuffer));
232 }
233}
234
235
236/* Update the display.
237 This must be called after all other LCD functions that change the display. */
238void lcd_update(void)
239{
240 lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT);
241}
242
243void lcd_bitmap_transparent_part(const fb_data *src, int src_x, int src_y,
244 int stride, int x, int y, int width,
245 int height)
246{
247 fb_data *dst, *dst_end;
248 unsigned int transcolor;
249
250 /* nothing to draw? */
251 if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT)
252 || (x + width <= 0) || (y + height <= 0))
253 return;
254
255 /* clipping */
256 if (x < 0)
257 {
258 width += x;
259 src_x -= x;
260 x = 0;
261 }
262 if (y < 0)
263 {
264 height += y;
265 src_y -= y;
266 y = 0;
267 }
268 if (x + width > LCD_WIDTH)
269 width = LCD_WIDTH - x;
270 if (y + height > LCD_HEIGHT)
271 height = LCD_HEIGHT - y;
272
273 src += stride * src_y + src_x; /* move starting point */
274 dst = &lcd_framebuffer[(y)][(x)];
275 dst_end = dst + height * LCD_WIDTH;
276 width *= 2;
277 stride *= 2;
278 transcolor = TRANSPARENT_COLOR;
279 asm volatile(
280 "rowstart: \n"
281 "mov r0, #0 \n"
282 "nextpixel: \n"
283 "ldrh r1, [%0, r0] \n" /* Load word src+r0 */
284 "cmp r1, %5 \n" /* Compare to transparent color */
285 "strneh r1, [%1, r0] \n" /* Store dst+r0 if not transparent */
286 "add r0, r0, #2 \n"
287 "cmp r0, %2 \n" /* r0 == width? */
288 "bne nextpixel \n" /* More in this row? */
289 "add %0, %0, %4 \n" /* src += stride */
290 "add %1, %1, #480 \n" /* dst += LCD_WIDTH (x2) */
291 "cmp %1, %3 \n"
292 "bne rowstart \n" /* if(dst != dst_end), keep going */
293 : : "r" (src), "r" (dst), "r" (width), "r" (dst_end), "r" (stride), "r" (transcolor) : "r0", "r1" );
294}
295
296/* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */
297extern void lcd_write_yuv420_lines(fb_data *dst,
298 unsigned char chroma_buf[LCD_HEIGHT/2*3],
299 unsigned char const * const src[3],
300 int width,
301 int stride);
302/* Performance function to blit a YUV bitmap directly to the LCD */
303/* For the Gigabeat - show it rotated */
304/* So the LCD_WIDTH is now the height */
305void lcd_yuv_blit(unsigned char * const src[3],
306 int src_x, int src_y, int stride,
307 int x, int y, int width, int height)
308{
309 /* Caches for chroma data so it only need be recaculated every other
310 line */
311 unsigned char chroma_buf[LCD_HEIGHT/2*3]; /* 480 bytes */
312 unsigned char const * yuv_src[3];
313 off_t z;
314
315 if (!lcd_on)
316 return;
317
318 /* Sorry, but width and height must be >= 2 or else */
319 width &= ~1;
320 height >>= 1;
321
322 fb_data *dst = (fb_data*)FRAME + x * LCD_WIDTH + (LCD_WIDTH - y) - 1;
323
324 z = stride*src_y;
325 yuv_src[0] = src[0] + z + src_x;
326 yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1);
327 yuv_src[2] = src[2] + (yuv_src[1] - src[1]);
328
329 do
330 {
331 lcd_write_yuv420_lines(dst, chroma_buf, yuv_src, width,
332 stride);
333 yuv_src[0] += stride << 1; /* Skip down two luma lines */
334 yuv_src[1] += stride >> 1; /* Skip down one chroma line */
335 yuv_src[2] += stride >> 1;
336 dst -= 2;
337 }
338 while (--height > 0);
339}
340
341void lcd_set_contrast(int val) {
342 (void) val;
343 // TODO:
344}
345
346void lcd_set_invert_display(bool yesno) {
347 (void) yesno;
348 // TODO:
349}
350
351void lcd_blit(const fb_data* data, int bx, int y, int bwidth,
352 int height, int stride)
353{
354 (void) data;
355 (void) bx;
356 (void) y;
357 (void) bwidth;
358 (void) height;
359 (void) stride;
360 //TODO:
361}
362
363void lcd_set_flip(bool yesno) {
364 (void) yesno;
365 // TODO:
366}
367