summaryrefslogtreecommitdiff
path: root/firmware/target/arm
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm')
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/lcd-as-meg-fx.S101
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c86
2 files changed, 146 insertions, 41 deletions
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/lcd-as-meg-fx.S b/firmware/target/arm/s3c2440/gigabeat-fx/lcd-as-meg-fx.S
index d431c95f29..f4805fd1e1 100644
--- a/firmware/target/arm/s3c2440/gigabeat-fx/lcd-as-meg-fx.S
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/lcd-as-meg-fx.S
@@ -21,6 +21,87 @@
21#include "cpu.h" 21#include "cpu.h"
22 22
23/**************************************************************************** 23/****************************************************************************
24 * void lcd_copy_buffer_rect(fb_data *dst, fb_data *src, int width,
25 * int height);
26 */
27 .section .icode, "ax", %progbits
28 .align 2
29 .global lcd_copy_buffer_rect
30 .type lcd_copy_buffer_rect, %function
31 @ r0 = dst
32 @ r1 = src
33 @ r2 = width
34 @ r3 = height
35lcd_copy_buffer_rect: @
36 stmfd sp!, { r4-r12, lr } @ save non-scratch regs
37 mov r5, r2 @ r5 = cached width
38 rsb r4, r2, #LCD_WIDTH @ r4 = LCD_WIDTH - width
3910: @ copy line @
40 subs r2, r5, #1 @ r2 = width - 1
41 beq 40f @ finish line @ one halfword? skip to trailing copy
42 tst r0, #2 @ word aligned?
43 beq 20f @ rem copy @ yes? skip to word copy
44 ldrh r6, [r1], #2 @ copy leading halfword
45 subs r2, r2, #1 @
46 strh r6, [r0], #2 @
47 ble 40f @ finish line @ next line if lt or finish
48 @ trailing halfword if eq
4920: @ rem copy @
50 add r14, r2, #1 @ get remaining width mod 16 after word
51 @ align (rw)
52 and r14, r14, #0xe @ r14 = 0 (16), 2, 4, 6, 8, 10, 12, 14
53 add pc, pc, r14, lsl #3 @ branch to 32-byte align
54 nop @
55 b 30f @ rw % 16 = 0 or 1? use octword loop
56 nop @
57 nop @
58 nop @
59 ldr r6, [r1], #4 @ rw % 16 = 2 or 3
60 subs r2, r2, #2 @
61 str r6, [r0], #4 @
62 b 25f @ copy up done @
63 ldmia r1!, { r6-r7 } @ rw % 16 = 4 or 5
64 subs r2, r2, #4 @
65 stmia r0!, { r6-r7 } @
66 b 25f @ copy up done @
67 ldmia r1!, { r6-r8 } @ rw % 16 = 6 or 7
68 subs r2, r2, #6 @
69 stmia r0!, { r6-r8 } @
70 b 25f @ copy up done @
71 ldmia r1!, { r6-r9 } @ rw % 16 = 8 or 9
72 subs r2, r2, #8 @
73 stmia r0!, { r6-r9 } @
74 b 25f @ copy up done @
75 ldmia r1!, { r6-r10 } @ rw % 16 = 10 or 11
76 subs r2, r2, #10 @
77 stmia r0!, { r6-r10 } @
78 b 25f @ copy up done @
79 ldmia r1!, { r6-r11 } @ rw % 16 = 12 or 13
80 subs r2, r2, #12 @
81 stmia r0!, { r6-r11 } @
82 b 25f @ copy up done @
83 ldmia r1!, { r6-r12 } @ rw % 16 = 14 or 15
84 subs r2, r2, #14 @
85 stmia r0!, { r6-r12 } @
8625: @ copy up done @
87 ble 40f @ finish line @ no 32-byte segments remaining?
8830: @ octword loop @ copy 16 pixels per loop
89 ldmia r1!, { r6-r12, r14 } @
90 subs r2, r2, #16 @
91 stmia r0!, { r6-r12, r14 } @
92 bgt 30b @ octword loop @
9340: @ finish line @
94 ldreqh r6, [r1], #2 @ finish last halfword if eq ...
95 add r1, r1, r4, lsl #1 @
96 streqh r6, [r0], #2 @ ...
97 add r0, r0, r4, lsl #1 @
98 subs r3, r3, #1 @ next line
99 bgt 10b @ copy line @
100 ldmfd sp!, { r4-r12, pc } @ restore regs and return
101 .size lcd_copy_buffer_rect, .-lcd_copy_buffer_rect
102
103
104/****************************************************************************
24 * void lcd_write_yuv_420_lines(fb_data *dst, 105 * void lcd_write_yuv_420_lines(fb_data *dst,
25 * unsigned char chroma_buf[LCD_HEIGHT/2*3], 106 * unsigned char chroma_buf[LCD_HEIGHT/2*3],
26 unsigned char const * const src[3], 107 unsigned char const * const src[3],
@@ -45,8 +126,8 @@ lcd_write_yuv420_lines:
45 @ r2 = yuv_src 126 @ r2 = yuv_src
46 @ r3 = width 127 @ r3 = width
47 @ [sp] = stride 128 @ [sp] = stride
48 stmdb sp!, { r4-r12, lr } @ save non-scratch 129 stmfd sp!, { r4-r12, lr } @ save non-scratch
49 stmdb sp!, { r0, r3 } @ save dst and width 130 stmfd sp!, { r0, r3 } @ save dst and width
50 mov r14, #74 @ r14 = Y factor 131 mov r14, #74 @ r14 = Y factor
51 ldmia r2, { r4, r5, r6 } @ r4 = yuv_src[0] = Y'_p 132 ldmia r2, { r4, r5, r6 } @ r4 = yuv_src[0] = Y'_p
52 @ r5 = yuv_src[1] = Cb_p 133 @ r5 = yuv_src[1] = Cb_p
@@ -105,7 +186,7 @@ lcd_write_yuv420_lines:
105 orr r12, r2, r7, lsl #5 @ r4 |= (g << 5) 186 orr r12, r2, r7, lsl #5 @ r4 |= (g << 5)
106 ldrb r2, [r4], #1 @ r2 = Y' = *Y'_p++ 187 ldrb r2, [r4], #1 @ r2 = Y' = *Y'_p++
107 orr r12, r12, r11, lsl #11 @ r4 = b | (r << 11) 188 orr r12, r12, r11, lsl #11 @ r4 = b | (r << 11)
108 strh r12, [r0], #240 @ store pixel 189 strh r12, [r0], #LCD_WIDTH @ store pixel
109 @ 190 @
110 sub r2, r2, #16 @ r7 = Y = (Y' - 16)*74 191 sub r2, r2, #16 @ r7 = Y = (Y' - 16)*74
111 mul r7, r2, r14 @ next Y 192 mul r7, r2, r14 @ next Y
@@ -133,14 +214,14 @@ lcd_write_yuv420_lines:
133 @ 214 @
134 orr r12, r2, r11, lsl #11 @ r4 = b | (r << 11) 215 orr r12, r2, r11, lsl #11 @ r4 = b | (r << 11)
135 orr r12, r12, r7, lsl #5 @ r4 |= (g << 5) 216 orr r12, r12, r7, lsl #5 @ r4 |= (g << 5)
136 strh r12, [r0, #240]! @ store pixel 217 strh r12, [r0, #LCD_WIDTH]! @ store pixel
137 add r0, r0, #2*240 @ 218 add r0, r0, #2*LCD_WIDTH @
138 @ 219 @
139 subs r3, r3, #2 @ 220 subs r3, r3, #2 @
140 bgt 10b @ loop line 1 @ 221 bgt 10b @ loop line 1 @
141 @ do second line 222 @ do second line
142 @ 223 @
143 ldmia sp!, { r0, r3 } @ pop dst and width 224 ldmfd sp!, { r0, r3 } @ pop dst and width
144 sub r0, r0, #2 @ set dst to start of next line 225 sub r0, r0, #2 @ set dst to start of next line
145 sub r1, r1, r3, asl #1 @ rewind chroma pointer... 226 sub r1, r1, r3, asl #1 @ rewind chroma pointer...
146 ldr r2, [sp, #40] @ r2 = stride 227 ldr r2, [sp, #40] @ r2 = stride
@@ -182,7 +263,7 @@ lcd_write_yuv420_lines:
182 orr r12, r2, r11, lsl #11 @ r4 = b | (r << 11) 263 orr r12, r2, r11, lsl #11 @ r4 = b | (r << 11)
183 ldrb r2, [r4], #1 @ r2 = Y' = *Y'_p++ 264 ldrb r2, [r4], #1 @ r2 = Y' = *Y'_p++
184 orr r12, r12, r7, lsl #5 @ r4 |= (g << 5) 265 orr r12, r12, r7, lsl #5 @ r4 |= (g << 5)
185 strh r12, [r0], #240 @ store pixel 266 strh r12, [r0], #LCD_WIDTH @ store pixel
186 @ 267 @
187 @ do second pixel 268 @ do second pixel
188 @ 269 @
@@ -212,11 +293,11 @@ lcd_write_yuv420_lines:
212 @ 293 @
213 orr r12, r2, r11, lsl #11 @ r4 = b | (r << 11) 294 orr r12, r2, r11, lsl #11 @ r4 = b | (r << 11)
214 orr r12, r12, r7, lsl #5 @ r4 |= (g << 5) 295 orr r12, r12, r7, lsl #5 @ r4 |= (g << 5)
215 strh r12, [r0, #240]! @ store pixel 296 strh r12, [r0, #LCD_WIDTH]! @ store pixel
216 add r0, r0, #2*240 @ 297 add r0, r0, #2*LCD_WIDTH @
217 @ 298 @
218 subs r3, r3, #2 @ 299 subs r3, r3, #2 @
219 bgt 20b @ loop line 2 @ 300 bgt 20b @ loop line 2 @
220 @ 301 @
221 ldmia sp!, { r4-r12, pc } @ restore registers and return 302 ldmfd sp!, { r4-r12, pc } @ restore registers and return
222 .size lcd_write_yuv420_lines, .-lcd_write_yuv420_lines 303 .size lcd_write_yuv420_lines, .-lcd_write_yuv420_lines
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c
index c96e0d6d25..5e1110eb3d 100644
--- a/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c
@@ -15,6 +15,12 @@ volatile bool lcd_poweroff = false;
15extern unsigned fg_pattern; 15extern unsigned fg_pattern;
16extern unsigned bg_pattern; 16extern unsigned bg_pattern;
17 17
18/* Copies a rectangle from one framebuffer to another. Can be used in
19 single transfer mode with width = num pixels, and height = 1 which
20 allows a full-width rectangle to be copied more efficiently. */
21extern void lcd_copy_buffer_rect(fb_data *dst, const fb_data *src,
22 int width, int height);
23
18bool lcd_enabled() 24bool lcd_enabled()
19{ 25{
20 return lcd_on; 26 return lcd_on;
@@ -36,7 +42,6 @@ unsigned int LCDBASEL(unsigned int address)
36 return (address & ((1 << 22)-1)) >> 1; 42 return (address & ((1 << 22)-1)) >> 1;
37} 43}
38 44
39
40/* LCD init */ 45/* LCD init */
41void lcd_init_device(void) 46void lcd_init_device(void)
42{ 47{
@@ -122,17 +127,41 @@ void lcd_init_device(void)
122/* Update a fraction of the display. */ 127/* Update a fraction of the display. */
123void lcd_update_rect(int x, int y, int width, int height) 128void lcd_update_rect(int x, int y, int width, int height)
124{ 129{
125 (void)x; 130 fb_data *dst, *src;
126 (void)width;
127 (void)y;
128 (void)height;
129 131
130 if(!lcd_on) 132 if (!lcd_on)
131 {
132 sleep(200);
133 return; 133 return;
134
135 if (x + width > LCD_WIDTH)
136 width = LCD_WIDTH - x; /* Clip right */
137 if (x < 0)
138 width += x, x = 0; /* Clip left */
139 if (width <= 0)
140 return; /* nothing left to do */
141
142 if (y + height > LCD_HEIGHT)
143 height = LCD_HEIGHT - y; /* Clip bottom */
144 if (y < 0)
145 height += y, y = 0; /* Clip top */
146 if (height <= 0)
147 return; /* nothing left to do */
148
149 /* TODO: It may be faster to swap the addresses of lcd_driver_framebuffer
150 * and lcd_framebuffer */
151 dst = (fb_data *)FRAME + LCD_WIDTH*y + x;
152 src = &lcd_framebuffer[y][x];
153
154 /* Copy part of the Rockbox framebuffer to the second framebuffer */
155 if (width < LCD_WIDTH)
156 {
157 /* Not full width - do line-by-line */
158 lcd_copy_buffer_rect(dst, src, width, height);
159 }
160 else
161 {
162 /* Full width - copy as one line */
163 lcd_copy_buffer_rect(dst, src, LCD_WIDTH*height, 1);
134 } 164 }
135 memcpy(((char*)FRAME) + (y * sizeof(fb_data) * LCD_WIDTH), ((char *)&lcd_framebuffer) + (y * sizeof(fb_data) * LCD_WIDTH), ((height * sizeof(fb_data) * LCD_WIDTH)));
136} 165}
137 166
138void lcd_enable(bool state) 167void lcd_enable(bool state)
@@ -144,7 +173,7 @@ void lcd_enable(bool state)
144 if(!lcd_on) 173 if(!lcd_on)
145 { 174 {
146 lcd_on = true; 175 lcd_on = true;
147 memcpy(FRAME, lcd_framebuffer, LCD_WIDTH*LCD_HEIGHT*2); 176 lcd_update();
148 LCDCON1 |= 1; 177 LCDCON1 |= 1;
149 } 178 }
150 } 179 }
@@ -161,7 +190,11 @@ void lcd_enable(bool state)
161 This must be called after all other LCD functions that change the display. */ 190 This must be called after all other LCD functions that change the display. */
162void lcd_update(void) 191void lcd_update(void)
163{ 192{
164 lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); 193 if (!lcd_on)
194 return;
195
196 lcd_copy_buffer_rect((fb_data *)FRAME, &lcd_framebuffer[0][0],
197 LCD_WIDTH*LCD_HEIGHT, 1);
165} 198}
166 199
167void lcd_bitmap_transparent_part(const fb_data *src, int src_x, int src_y, 200void lcd_bitmap_transparent_part(const fb_data *src, int src_x, int src_y,
@@ -171,28 +204,19 @@ void lcd_bitmap_transparent_part(const fb_data *src, int src_x, int src_y,
171 fb_data *dst, *dst_end; 204 fb_data *dst, *dst_end;
172 unsigned int transcolor; 205 unsigned int transcolor;
173 206
174 /* nothing to draw? */
175 if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT)
176 || (x + width <= 0) || (y + height <= 0))
177 return;
178
179 /* clipping */
180 if (x < 0)
181 {
182 width += x;
183 src_x -= x;
184 x = 0;
185 }
186 if (y < 0)
187 {
188 height += y;
189 src_y -= y;
190 y = 0;
191 }
192 if (x + width > LCD_WIDTH) 207 if (x + width > LCD_WIDTH)
193 width = LCD_WIDTH - x; 208 width = LCD_WIDTH - x; /* Clip right */
209 if (x < 0)
210 width += x, x = 0; /* Clip left */
211 if (width <= 0)
212 return; /* nothing left to do */
213
194 if (y + height > LCD_HEIGHT) 214 if (y + height > LCD_HEIGHT)
195 height = LCD_HEIGHT - y; 215 height = LCD_HEIGHT - y; /* Clip bottom */
216 if (y < 0)
217 height += y, y = 0; /* Clip top */
218 if (height <= 0)
219 return; /* nothing left to do */
196 220
197 src += stride * src_y + src_x; /* move starting point */ 221 src += stride * src_y + src_x; /* move starting point */
198 dst = &lcd_framebuffer[(y)][(x)]; 222 dst = &lcd_framebuffer[(y)][(x)];