diff options
author | Rafaël Carré <rafael.carre@gmail.com> | 2009-05-12 13:22:39 +0000 |
---|---|---|
committer | Rafaël Carré <rafael.carre@gmail.com> | 2009-05-12 13:22:39 +0000 |
commit | b1d03ccee7066d7e8e218b7cafcd85b17f5549d8 (patch) | |
tree | dc0039d583343471b3e3315fd04625fe9212e567 | |
parent | f2c18d6922257c6610f4c01ed09ce318295bee68 (diff) | |
download | rockbox-b1d03ccee7066d7e8e218b7cafcd85b17f5549d8.tar.gz rockbox-b1d03ccee7066d7e8e218b7cafcd85b17f5549d8.zip |
FS#10118 & FS#10165 : lcd_blit_yuv() for Sansa Fuze & Sansa e200v2
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20919 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | apps/plugin.c | 2 | ||||
-rw-r--r-- | apps/plugin.h | 2 | ||||
-rw-r--r-- | apps/plugins/mpegplayer/mpeg_settings.c | 2 | ||||
-rw-r--r-- | apps/plugins/mpegplayer/mpeg_settings.h | 3 | ||||
-rw-r--r-- | firmware/SOURCES | 2 | ||||
-rw-r--r-- | firmware/target/arm/as3525/lcd-as-e200v2-fuze.S | 501 | ||||
-rw-r--r-- | firmware/target/arm/as3525/sansa-e200v2/lcd-e200v2.c | 99 | ||||
-rw-r--r-- | firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c | 121 |
8 files changed, 681 insertions, 51 deletions
diff --git a/apps/plugin.c b/apps/plugin.c index f079e849bd..7f362c8566 100644 --- a/apps/plugin.c +++ b/apps/plugin.c | |||
@@ -128,7 +128,7 @@ static const struct plugin_api rockbox_api = { | |||
128 | lcd_bitmap_transparent, | 128 | lcd_bitmap_transparent, |
129 | lcd_blit_yuv, | 129 | lcd_blit_yuv, |
130 | #if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200) || defined(SANSA_C200) \ | 130 | #if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200) || defined(SANSA_C200) \ |
131 | || defined(IRIVER_H10) || defined(COWON_D2) || defined(PHILIPS_HDD1630) | 131 | || defined(IRIVER_H10) || defined(COWON_D2) || defined(PHILIPS_HDD1630) || defined(SANSA_FUZE) || defined(SANSA_E200V2) |
132 | lcd_yuv_set_options, | 132 | lcd_yuv_set_options, |
133 | #endif | 133 | #endif |
134 | #elif (LCD_DEPTH < 4) && !defined(SIMULATOR) | 134 | #elif (LCD_DEPTH < 4) && !defined(SIMULATOR) |
diff --git a/apps/plugin.h b/apps/plugin.h index 5efe3fe00c..f48e7e23ee 100644 --- a/apps/plugin.h +++ b/apps/plugin.h | |||
@@ -210,7 +210,7 @@ struct plugin_api { | |||
210 | int src_x, int src_y, int stride, | 210 | int src_x, int src_y, int stride, |
211 | int x, int y, int width, int height); | 211 | int x, int y, int width, int height); |
212 | #if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200) || defined(SANSA_C200) \ | 212 | #if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200) || defined(SANSA_C200) \ |
213 | || defined(IRIVER_H10) || defined(COWON_D2) || defined(PHILIPS_HDD1630) | 213 | || defined(IRIVER_H10) || defined(COWON_D2) || defined(PHILIPS_HDD1630) || defined(SANSA_FUZE) || defined(SANSA_E200V2) |
214 | void (*lcd_yuv_set_options)(unsigned options); | 214 | void (*lcd_yuv_set_options)(unsigned options); |
215 | #endif | 215 | #endif |
216 | #elif (LCD_DEPTH < 4) && !defined(SIMULATOR) | 216 | #elif (LCD_DEPTH < 4) && !defined(SIMULATOR) |
diff --git a/apps/plugins/mpegplayer/mpeg_settings.c b/apps/plugins/mpegplayer/mpeg_settings.c index 3edb2987a1..189bdbcde7 100644 --- a/apps/plugins/mpegplayer/mpeg_settings.c +++ b/apps/plugins/mpegplayer/mpeg_settings.c | |||
@@ -205,7 +205,7 @@ static struct configdata config[] = | |||
205 | NULL}, | 205 | NULL}, |
206 | {TYPE_INT, 0, MPEG_RESUME_NUM_OPTIONS, | 206 | {TYPE_INT, 0, MPEG_RESUME_NUM_OPTIONS, |
207 | { .int_p = &settings.resume_options }, "Resume options", NULL}, | 207 | { .int_p = &settings.resume_options }, "Resume options", NULL}, |
208 | #if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200) || defined(SANSA_C200) | 208 | #if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200) || defined(SANSA_C200) || defined(SANSA_FUZE) || defined(SANSA_E200V2) |
209 | {TYPE_INT, 0, INT_MAX, { .int_p = &settings.displayoptions }, | 209 | {TYPE_INT, 0, INT_MAX, { .int_p = &settings.displayoptions }, |
210 | "Display options", NULL}, | 210 | "Display options", NULL}, |
211 | #endif | 211 | #endif |
diff --git a/apps/plugins/mpegplayer/mpeg_settings.h b/apps/plugins/mpegplayer/mpeg_settings.h index 6de9e698b0..fc43db036b 100644 --- a/apps/plugins/mpegplayer/mpeg_settings.h +++ b/apps/plugins/mpegplayer/mpeg_settings.h | |||
@@ -6,7 +6,8 @@ | |||
6 | #define SETTINGS_FILENAME "mpegplayer.cfg" | 6 | #define SETTINGS_FILENAME "mpegplayer.cfg" |
7 | 7 | ||
8 | #if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200) || defined(SANSA_C200) \ | 8 | #if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200) || defined(SANSA_C200) \ |
9 | || defined(IRIVER_H10) || defined(COWON_D2) || defined(PHILIPS_HDD1630) | 9 | || defined(IRIVER_H10) || defined(COWON_D2) || defined(PHILIPS_HDD1630) \ |
10 | || defined(SANSA_FUZE) || defined(SANSA_E200V2) | ||
10 | #define MPEG_OPTION_DITHERING_ENABLED 1 | 11 | #define MPEG_OPTION_DITHERING_ENABLED 1 |
11 | #endif | 12 | #endif |
12 | 13 | ||
diff --git a/firmware/SOURCES b/firmware/SOURCES index d96dc8c8a9..7a00bb903a 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES | |||
@@ -1108,6 +1108,7 @@ target/arm/as3525/sansa-clip/powermgmt-clip.c | |||
1108 | #ifdef SANSA_E200V2 | 1108 | #ifdef SANSA_E200V2 |
1109 | #ifndef SIMULATOR | 1109 | #ifndef SIMULATOR |
1110 | target/arm/as3525/sansa-e200v2/lcd-e200v2.c | 1110 | target/arm/as3525/sansa-e200v2/lcd-e200v2.c |
1111 | target/arm/as3525/lcd-as-e200v2-fuze.S | ||
1111 | target/arm/as3525/sansa-e200v2/button-e200v2.c | 1112 | target/arm/as3525/sansa-e200v2/button-e200v2.c |
1112 | target/arm/as3525/backlight-e200v2-fuze.c | 1113 | target/arm/as3525/backlight-e200v2-fuze.c |
1113 | #ifndef BOOTLOADER | 1114 | #ifndef BOOTLOADER |
@@ -1142,6 +1143,7 @@ target/arm/as3525/sansa-m200v4/powermgmt-m200v4.c | |||
1142 | #ifndef SIMULATOR | 1143 | #ifndef SIMULATOR |
1143 | target/arm/as3525/sansa-fuze/button-fuze.c | 1144 | target/arm/as3525/sansa-fuze/button-fuze.c |
1144 | target/arm/as3525/sansa-fuze/lcd-fuze.c | 1145 | target/arm/as3525/sansa-fuze/lcd-fuze.c |
1146 | target/arm/as3525/lcd-as-e200v2-fuze.S | ||
1145 | target/arm/as3525/backlight-e200v2-fuze.c | 1147 | target/arm/as3525/backlight-e200v2-fuze.c |
1146 | #ifndef BOOTLOADER | 1148 | #ifndef BOOTLOADER |
1147 | target/arm/as3525/powermgmt-as3525.c | 1149 | target/arm/as3525/powermgmt-as3525.c |
diff --git a/firmware/target/arm/as3525/lcd-as-e200v2-fuze.S b/firmware/target/arm/as3525/lcd-as-e200v2-fuze.S new file mode 100644 index 0000000000..254816cd0e --- /dev/null +++ b/firmware/target/arm/as3525/lcd-as-e200v2-fuze.S | |||
@@ -0,0 +1,501 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2007 by Jens Arnold | ||
11 | * Heavily based on lcd-as-memframe.c by Michael Sevakis | ||
12 | * Adapted for Sansa Fuze/e200v2 by Rafaël Carré | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or | ||
15 | * modify it under the terms of the GNU General Public License | ||
16 | * as published by the Free Software Foundation; either version 2 | ||
17 | * of the License, or (at your option) any later version. | ||
18 | * | ||
19 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
20 | * KIND, either express or implied. | ||
21 | * | ||
22 | ****************************************************************************/ | ||
23 | |||
24 | #include "config.h" | ||
25 | #include "cpu.h" | ||
26 | |||
27 | #define DBOP_BUSY (1<<10) | ||
28 | |||
29 | /**************************************************************************** | ||
30 | * void lcd_write_yuv_420_lines(unsigned char const * const src[3], | ||
31 | * int width, | ||
32 | * int stride); | ||
33 | * | ||
34 | * |R| |1.000000 -0.000001 1.402000| |Y'| | ||
35 | * |G| = |1.000000 -0.334136 -0.714136| |Pb| | ||
36 | * |B| |1.000000 1.772000 0.000000| |Pr| | ||
37 | * Scaled, normalized, rounded and tweaked to yield RGB 565: | ||
38 | * |R| |74 0 101| |Y' - 16| >> 9 | ||
39 | * |G| = |74 -24 -51| |Cb - 128| >> 8 | ||
40 | * |B| |74 128 0| |Cr - 128| >> 9 | ||
41 | * | ||
42 | * Write four RGB565 pixels in the following order on each loop: | ||
43 | * 1 3 + > down | ||
44 | * 2 4 \/ left | ||
45 | */ | ||
46 | .section .icode, "ax", %progbits | ||
47 | .align 2 | ||
48 | .global lcd_write_yuv420_lines | ||
49 | .type lcd_write_yuv420_lines, %function | ||
50 | lcd_write_yuv420_lines: | ||
51 | @ r0 = yuv_src | ||
52 | @ r1 = width | ||
53 | @ r2 = stride | ||
54 | stmfd sp!, { r4-r12 } @ save non-scratch | ||
55 | ldmia r0, { r4, r5, r6 } @ r4 = yuv_src[0] = Y'_p | ||
56 | @ r5 = yuv_src[1] = Cb_p | ||
57 | @ r6 = yuv_src[2] = Cr_p | ||
58 | @ r0 = scratch | ||
59 | sub r2, r2, #1 @ | ||
60 | mov r3, #0xC8000000 @ | ||
61 | orr r3, r3, #0x120000 @ r3 = DBOP_BASE | ||
62 | 10: @ loop line @ | ||
63 | ldrb r7, [r4], #1 @ r7 = *Y'_p++; | ||
64 | ldrb r8, [r5], #1 @ r8 = *Cb_p++; | ||
65 | ldrb r9, [r6], #1 @ r9 = *Cr_p++; | ||
66 | @ | ||
67 | sub r7, r7, #16 @ r7 = Y = (Y' - 16)*74 | ||
68 | add r12, r7, r7, asl #2 @ actually (Y' - 16)*37 and shift right | ||
69 | add r7, r12, r7, asl #5 @ by one less when adding - same for all | ||
70 | @ | ||
71 | sub r8, r8, #128 @ Cb -= 128 | ||
72 | sub r9, r9, #128 @ Cr -= 128 | ||
73 | @ | ||
74 | add r10, r9, r9, asl #1 @ r10 = Cr*51 + Cb*24 | ||
75 | add r10, r10, r10, asl #4 @ | ||
76 | add r10, r10, r8, asl #3 @ | ||
77 | add r10, r10, r8, asl #4 @ | ||
78 | @ | ||
79 | add r11, r9, r9, asl #2 @ r9 = Cr*101 | ||
80 | add r11, r11, r9, asl #5 @ | ||
81 | add r9, r11, r9, asl #6 @ | ||
82 | @ | ||
83 | add r8, r8, #2 @ r8 = bu = (Cb*128 + 128) >> 8 | ||
84 | mov r8, r8, asr #2 @ | ||
85 | add r9, r9, #256 @ r9 = rv = (r9 + 256) >> 9 | ||
86 | mov r9, r9, asr #9 @ | ||
87 | rsb r10, r10, #128 @ r10 = guv = (-r10 + 128) >> 8 | ||
88 | mov r10, r10, asr #8 @ | ||
89 | @ compute R, G, and B | ||
90 | add r0, r8, r7, asr #8 @ r0 = b = (Y >> 9) + bu | ||
91 | add r11, r9, r7, asr #8 @ r11 = r = (Y >> 9) + rv | ||
92 | add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv | ||
93 | @ | ||
94 | orr r12, r0, r11 @ check if clamping is needed... | ||
95 | orr r12, r12, r7, asr #1 @ ...at all | ||
96 | cmp r12, #31 @ | ||
97 | bls 15f @ no clamp @ | ||
98 | cmp r0, #31 @ clamp b | ||
99 | mvnhi r0, r0, asr #31 @ | ||
100 | andhi r0, r0, #31 @ | ||
101 | cmp r11, #31 @ clamp r | ||
102 | mvnhi r11, r11, asr #31 @ | ||
103 | andhi r11, r11, #31 @ | ||
104 | cmp r7, #63 @ clamp g | ||
105 | mvnhi r7, r7, asr #31 @ | ||
106 | andhi r7, r7, #63 @ | ||
107 | 15: @ no clamp @ | ||
108 | @ | ||
109 | ldrb r12, [r4, r2] @ r12 = Y' = *(Y'_p + stride) | ||
110 | @ | ||
111 | orr r0, r0, r11, lsl #11 @ r0 = (r << 11) | b | ||
112 | orr r0, r0, r7, lsl #5 @ r0 = (r << 11) | (g << 5) | b | ||
113 | strh r0, [r3, #0x10] @ write pixel | ||
114 | 1: @ busy @ | ||
115 | ldr r7, [r3,#0xc] @ r7 = DBOP_STATUS | ||
116 | tst r7, #DBOP_BUSY @ fifo not empty? | ||
117 | beq 1b @ | ||
118 | @ | ||
119 | sub r7, r12, #16 @ r7 = Y = (Y' - 16)*74 | ||
120 | add r12, r7, r7, asl #2 @ | ||
121 | add r7, r12, r7, asl #5 @ | ||
122 | @ compute R, G, and B | ||
123 | add r0, r8, r7, asr #8 @ r0 = b = (Y >> 9) + bu | ||
124 | add r11, r9, r7, asr #8 @ r11 = r = (Y >> 9) + rv | ||
125 | add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv | ||
126 | @ | ||
127 | orr r12, r0, r11 @ check if clamping is needed... | ||
128 | orr r12, r12, r7, asr #1 @ ...at all | ||
129 | cmp r12, #31 @ | ||
130 | bls 15f @ no clamp @ | ||
131 | cmp r0, #31 @ clamp b | ||
132 | mvnhi r0, r0, asr #31 @ | ||
133 | andhi r0, r0, #31 @ | ||
134 | cmp r11, #31 @ clamp r | ||
135 | mvnhi r11, r11, asr #31 @ | ||
136 | andhi r11, r11, #31 @ | ||
137 | cmp r7, #63 @ clamp g | ||
138 | mvnhi r7, r7, asr #31 @ | ||
139 | andhi r7, r7, #63 @ | ||
140 | 15: @ no clamp @ | ||
141 | @ | ||
142 | ldrb r12, [r4], #1 @ r12 = Y' = *(Y'_p++) | ||
143 | @ | ||
144 | orr r0, r0, r11, lsl #11 @ r0 = (r << 11) | b | ||
145 | orr r0, r0, r7, lsl #5 @ r0 = (r << 11) | (g << 5) | b | ||
146 | strh r0, [r3, #0x10] @ write pixel | ||
147 | 1: @ busy @ | ||
148 | ldr r7, [r3,#0xc] @ r7 = DBOP_STATUS | ||
149 | tst r7, #DBOP_BUSY @ fifo not empty? | ||
150 | beq 1b @ | ||
151 | @ | ||
152 | sub r7, r12, #16 @ r7 = Y = (Y' - 16)*74 | ||
153 | add r12, r7, r7, asl #2 @ | ||
154 | add r7, r12, r7, asl #5 @ | ||
155 | @ compute R, G, and B | ||
156 | add r0, r8, r7, asr #8 @ r0 = b = (Y >> 9) + bu | ||
157 | add r11, r9, r7, asr #8 @ r11 = r = (Y >> 9) + rv | ||
158 | add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv | ||
159 | @ | ||
160 | orr r12, r0, r11 @ check if clamping is needed... | ||
161 | orr r12, r12, r7, asr #1 @ ...at all | ||
162 | cmp r12, #31 @ | ||
163 | bls 15f @ no clamp @ | ||
164 | cmp r0, #31 @ clamp b | ||
165 | mvnhi r0, r0, asr #31 @ | ||
166 | andhi r0, r0, #31 @ | ||
167 | cmp r11, #31 @ clamp r | ||
168 | mvnhi r11, r11, asr #31 @ | ||
169 | andhi r11, r11, #31 @ | ||
170 | cmp r7, #63 @ clamp g | ||
171 | mvnhi r7, r7, asr #31 @ | ||
172 | andhi r7, r7, #63 @ | ||
173 | 15: @ no clamp @ | ||
174 | @ | ||
175 | ldrb r12, [r4, r2] @ r12 = Y' = *(Y'_p + stride) | ||
176 | @ | ||
177 | @ | ||
178 | orr r0, r0, r11, lsl #11 @ r0 = (r << 11) | b | ||
179 | orr r0, r0, r7, lsl #5 @ r0 = (r << 11) | (g << 5) | b | ||
180 | strh r0, [r3, #0x10] @ write pixel | ||
181 | 1: @ busy @ | ||
182 | ldr r7, [r3,#0xc] @ r7 = DBOP_STATUS | ||
183 | tst r7, #DBOP_BUSY @ fifo not empty? | ||
184 | beq 1b @ | ||
185 | @ | ||
186 | sub r7, r12, #16 @ r7 = Y = (Y' - 16)*74 | ||
187 | add r12, r7, r7, asl #2 @ | ||
188 | add r7, r12, r7, asl #5 @ | ||
189 | @ compute R, G, and B | ||
190 | add r0, r8, r7, asr #8 @ r0 = b = (Y >> 9) + bu | ||
191 | add r11, r9, r7, asr #8 @ r11 = r = (Y >> 9) + rv | ||
192 | add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv | ||
193 | @ | ||
194 | orr r12, r0, r11 @ check if clamping is needed... | ||
195 | orr r12, r12, r7, asr #1 @ ...at all | ||
196 | cmp r12, #31 @ | ||
197 | bls 15f @ no clamp @ | ||
198 | cmp r0, #31 @ clamp b | ||
199 | mvnhi r0, r0, asr #31 @ | ||
200 | andhi r0, r0, #31 @ | ||
201 | cmp r11, #31 @ clamp r | ||
202 | mvnhi r11, r11, asr #31 @ | ||
203 | andhi r11, r11, #31 @ | ||
204 | cmp r7, #63 @ clamp g | ||
205 | mvnhi r7, r7, asr #31 @ | ||
206 | andhi r7, r7, #63 @ | ||
207 | 15: @ no clamp @ | ||
208 | @ | ||
209 | orr r0, r0, r11, lsl #11 @ r0 = (r << 11) | b | ||
210 | orr r0, r0, r7, lsl #5 @ r0 = (r << 11) | (g << 5) | b | ||
211 | strh r0, [r3, #0x10] @ write pixel | ||
212 | 1: @ busy @ | ||
213 | ldr r7, [r3,#0xc] @ r7 = DBOP_STATUS | ||
214 | tst r7, #DBOP_BUSY @ fifo not empty? | ||
215 | beq 1b @ | ||
216 | @ | ||
217 | subs r1, r1, #2 @ subtract block from width | ||
218 | bgt 10b @ loop line @ | ||
219 | @ | ||
220 | ldmfd sp!, { r4-r12 } @ restore registers and return | ||
221 | bx lr @ | ||
222 | .ltorg @ dump constant pool | ||
223 | .size lcd_write_yuv420_lines, .-lcd_write_yuv420_lines | ||
224 | |||
225 | /**************************************************************************** | ||
226 | * void lcd_write_yuv_420_lines_odither(unsigned char const * const src[3], | ||
227 | * int width, | ||
228 | * int stride, | ||
229 | * int x_screen, | ||
230 | * int y_screen); | ||
231 | * | ||
232 | * |R| |1.000000 -0.000001 1.402000| |Y'| | ||
233 | * |G| = |1.000000 -0.334136 -0.714136| |Pb| | ||
234 | * |B| |1.000000 1.772000 0.000000| |Pr| | ||
235 | * Red scaled at twice g & b but at same precision to place it in correct | ||
236 | * bit position after multiply and leave instruction count lower. | ||
237 | * |R| |258 0 408| |Y' - 16| | ||
238 | * |G| = |149 -49 -104| |Cb - 128| | ||
239 | * |B| |149 258 0| |Cr - 128| | ||
240 | * | ||
241 | * Write four RGB565 pixels in the following order on each loop: | ||
242 | * 1 3 + > down | ||
243 | * 2 4 \/ left | ||
244 | * | ||
245 | * Kernel pattern (raw|rotated|use order): | ||
246 | * 5 3 4 2 2 6 3 7 row0 row2 > down | ||
247 | * 1 7 0 6 | 4 0 5 1 | 2 4 6 0 3 5 7 1 col0 left | ||
248 | * 4 2 5 3 | 3 7 2 6 | 3 5 7 1 2 4 6 0 col2 \/ | ||
249 | * 0 6 1 7 5 1 4 0 | ||
250 | */ | ||
251 | .section .icode, "ax", %progbits | ||
252 | .align 2 | ||
253 | .global lcd_write_yuv420_lines_odither | ||
254 | .type lcd_write_yuv420_lines_odither, %function | ||
255 | lcd_write_yuv420_lines_odither: | ||
256 | @ r0 = yuv_src | ||
257 | @ r1 = width | ||
258 | @ r2 = stride | ||
259 | @ r3 = x_screen | ||
260 | @ [sp] = y_screen | ||
261 | stmfd sp!, { r4-r12, lr } @ save non-scratch | ||
262 | ldmia r0, { r4, r5, r6 } @ r4 = yuv_src[0] = Y'_p | ||
263 | @ r5 = yuv_src[1] = Cb_p | ||
264 | @ r6 = yuv_src[2] = Cr_p | ||
265 | @ | ||
266 | sub r2, r2, #1 @ | ||
267 | ldr r14, [sp, #40] @ Line up pattern and kernel quadrant | ||
268 | eor r14, r14, r3 @ | ||
269 | and r14, r14, #0x2 @ | ||
270 | mov r14, r14, lsl #6 @ 0x00 or 0x80 | ||
271 | mov r3, #0xC8000000 @ | ||
272 | orr r3, r3, #0x120000 @ r3 = DBOP_BASE | ||
273 | 10: @ loop line @ | ||
274 | @ | ||
275 | ldrb r7, [r4], #1 @ r7 = *Y'_p++; | ||
276 | ldrb r8, [r5], #1 @ r8 = *Cb_p++; | ||
277 | ldrb r9, [r6], #1 @ r9 = *Cr_p++; | ||
278 | @ | ||
279 | eor r14, r14, #0x80 @ flip pattern quadrant | ||
280 | @ | ||
281 | sub r7, r7, #16 @ r7 = Y = (Y' - 16)*149 | ||
282 | add r12, r7, r7, asl #2 @ | ||
283 | add r12, r12, r12, asl #4 @ | ||
284 | add r7, r12, r7, asl #6 @ | ||
285 | @ | ||
286 | sub r8, r8, #128 @ Cb -= 128 | ||
287 | sub r9, r9, #128 @ Cr -= 128 | ||
288 | @ | ||
289 | add r10, r8, r8, asl #4 @ r10 = guv = Cr*104 + Cb*49 | ||
290 | add r10, r10, r8, asl #5 @ | ||
291 | add r10, r10, r9, asl #3 @ | ||
292 | add r10, r10, r9, asl #5 @ | ||
293 | add r10, r10, r9, asl #6 @ | ||
294 | @ | ||
295 | mov r8, r8, asl #1 @ r8 = bu = Cb*258 | ||
296 | add r8, r8, r8, asl #7 @ | ||
297 | @ | ||
298 | add r9, r9, r9, asl #1 @ r9 = rv = Cr*408 | ||
299 | add r9, r9, r9, asl #4 @ | ||
300 | mov r9, r9, asl #3 @ | ||
301 | @ | ||
302 | @ compute R, G, and B | ||
303 | add r0, r8, r7 @ r0 = b' = Y + bu | ||
304 | add r11, r9, r7, asl #1 @ r11 = r' = Y*2 + rv | ||
305 | rsb r7, r10, r7 @ r7 = g' = Y + guv | ||
306 | @ | ||
307 | @ r8 = bu, r9 = rv, r10 = guv | ||
308 | @ | ||
309 | sub r12, r0, r0, lsr #5 @ r0 = 31/32*b + b/256 | ||
310 | add r0, r12, r0, lsr #8 @ | ||
311 | @ | ||
312 | sub r12, r11, r11, lsr #5 @ r11 = 31/32*r + r/256 | ||
313 | add r11, r12, r11, lsr #8 @ | ||
314 | @ | ||
315 | sub r12, r7, r7, lsr #6 @ r7 = 63/64*g + g/256 | ||
316 | add r7, r12, r7, lsr #8 @ | ||
317 | @ | ||
318 | add r12, r14, #0x100 @ | ||
319 | @ | ||
320 | add r0, r0, r12 @ b = r0 + delta | ||
321 | add r11, r11, r12, lsl #1 @ r = r11 + delta*2 | ||
322 | add r7, r7, r12, lsr #1 @ g = r7 + delta/2 | ||
323 | @ | ||
324 | orr r12, r0, r11, asr #1 @ check if clamping is needed... | ||
325 | orr r12, r12, r7 @ ...at all | ||
326 | movs r12, r12, asr #15 @ | ||
327 | beq 15f @ no clamp @ | ||
328 | movs r12, r0, asr #15 @ clamp b | ||
329 | mvnne r0, r12, lsr #15 @ | ||
330 | andne r0, r0, #0x7c00 @ mask b only if clamped | ||
331 | movs r12, r11, asr #16 @ clamp r | ||
332 | mvnne r11, r12, lsr #16 @ | ||
333 | movs r12, r7, asr #15 @ clamp g | ||
334 | mvnne r7, r12, lsr #15 @ | ||
335 | 15: @ no clamp @ | ||
336 | @ | ||
337 | ldrb r12, [r4, r2] @ r12 = Y' = *(Y'_p + stride) | ||
338 | @ | ||
339 | and r11, r11, #0xf800 @ pack pixel | ||
340 | and r7, r7, #0x7e00 @ r0 = pixel = (r & 0xf800) | | ||
341 | orr r11, r11, r7, lsr #4 @ ((g & 0x7e00) >> 4) | | ||
342 | orr r0, r11, r0, lsr #10 @ (b >> 10) | ||
343 | strh r0, [r3, #0x10] @ write pixel | ||
344 | 1: @ busy @ | ||
345 | ldr r7, [r3,#0xc] @ r7 = DBOP_STATUS | ||
346 | tst r7, #DBOP_BUSY @ fifo not empty? | ||
347 | beq 1b @ | ||
348 | @ | ||
349 | sub r7, r12, #16 @ r7 = Y = (Y' - 16)*149 | ||
350 | add r12, r7, r7, asl #2 @ | ||
351 | add r12, r12, r12, asl #4 @ | ||
352 | add r7, r12, r7, asl #6 @ | ||
353 | @ compute R, G, and B | ||
354 | add r0, r8, r7 @ r0 = b' = Y + bu | ||
355 | add r11, r9, r7, asl #1 @ r11 = r' = Y*2 + rv | ||
356 | rsb r7, r10, r7 @ r7 = g' = Y + guv | ||
357 | @ | ||
358 | sub r12, r0, r0, lsr #5 @ r0 = 31/32*b' + b'/256 | ||
359 | add r0, r12, r0, lsr #8 @ | ||
360 | @ | ||
361 | sub r12, r11, r11, lsr #5 @ r11 = 31/32*r' + r'/256 | ||
362 | add r11, r12, r11, lsr #8 @ | ||
363 | @ | ||
364 | sub r12, r7, r7, lsr #6 @ r7 = 63/64*g' + g'/256 | ||
365 | add r7, r12, r7, lsr #8 @ | ||
366 | @ | ||
367 | add r12, r14, #0x200 @ | ||
368 | @ | ||
369 | add r0, r0, r12 @ b = r0 + delta | ||
370 | add r11, r11, r12, lsl #1 @ r = r11 + delta*2 | ||
371 | add r7, r7, r12, lsr #1 @ g = r7 + delta/2 | ||
372 | @ | ||
373 | orr r12, r0, r11, asr #1 @ check if clamping is needed... | ||
374 | orr r12, r12, r7 @ ...at all | ||
375 | movs r12, r12, asr #15 @ | ||
376 | beq 15f @ no clamp @ | ||
377 | movs r12, r0, asr #15 @ clamp b | ||
378 | mvnne r0, r12, lsr #15 @ | ||
379 | andne r0, r0, #0x7c00 @ mask b only if clamped | ||
380 | movs r12, r11, asr #16 @ clamp r | ||
381 | mvnne r11, r12, lsr #16 @ | ||
382 | movs r12, r7, asr #15 @ clamp g | ||
383 | mvnne r7, r12, lsr #15 @ | ||
384 | 15: @ no clamp @ | ||
385 | @ | ||
386 | ldrb r12, [r4], #1 @ r12 = Y' = *(Y'_p++) | ||
387 | |||
388 | and r11, r11, #0xf800 @ pack pixel | ||
389 | and r7, r7, #0x7e00 @ r0 = pixel = (r & 0xf800) | | ||
390 | orr r11, r11, r7, lsr #4 @ ((g & 0x7e00) >> 4) | | ||
391 | orr r0, r11, r0, lsr #10 @ (b >> 10) | ||
392 | strh r0, [r3, #0x10] @ write pixel | ||
393 | 1: @ busy @ | ||
394 | ldr r7, [r3,#0xc] @ r7 = DBOP_STATUS | ||
395 | tst r7, #DBOP_BUSY @ fifo not empty? | ||
396 | beq 1b @ | ||
397 | @ | ||
398 | sub r7, r12, #16 @ r7 = Y = (Y' - 16)*149 | ||
399 | add r12, r7, r7, asl #2 @ | ||
400 | add r12, r12, r12, asl #4 @ | ||
401 | add r7, r12, r7, asl #6 @ | ||
402 | @ compute R, G, and B | ||
403 | add r0, r8, r7 @ r0 = b' = Y + bu | ||
404 | add r11, r9, r7, asl #1 @ r11 = r' = Y*2 + rv | ||
405 | rsb r7, r10, r7 @ r7 = g' = Y + guv | ||
406 | @ | ||
407 | @ r8 = bu, r9 = rv, r10 = guv | ||
408 | @ | ||
409 | sub r12, r0, r0, lsr #5 @ r0 = 31/32*b' + b'/256 | ||
410 | add r0, r12, r0, lsr #8 @ | ||
411 | @ | ||
412 | sub r12, r11, r11, lsr #5 @ r11 = 31/32*r' + r'/256 | ||
413 | add r11, r12, r11, lsr #8 @ | ||
414 | @ | ||
415 | sub r12, r7, r7, lsr #6 @ r7 = 63/64*g' + g'/256 | ||
416 | add r7, r12, r7, lsr #8 @ | ||
417 | @ | ||
418 | add r12, r14, #0x300 @ | ||
419 | @ | ||
420 | add r0, r0, r12 @ b = r0 + delta | ||
421 | add r11, r11, r12, lsl #1 @ r = r11 + delta*2 | ||
422 | add r7, r7, r12, lsr #1 @ g = r7 + delta/2 | ||
423 | @ | ||
424 | orr r12, r0, r11, asr #1 @ check if clamping is needed... | ||
425 | orr r12, r12, r7 @ ...at all | ||
426 | movs r12, r12, asr #15 @ | ||
427 | beq 15f @ no clamp @ | ||
428 | movs r12, r0, asr #15 @ clamp b | ||
429 | mvnne r0, r12, lsr #15 @ | ||
430 | andne r0, r0, #0x7c00 @ mask b only if clamped | ||
431 | movs r12, r11, asr #16 @ clamp r | ||
432 | mvnne r11, r12, lsr #16 @ | ||
433 | movs r12, r7, asr #15 @ clamp g | ||
434 | mvnne r7, r12, lsr #15 @ | ||
435 | 15: @ no clamp @ | ||
436 | @ | ||
437 | ldrb r12, [r4, r2] @ r12 = Y' = *(Y'_p + stride) | ||
438 | @ | ||
439 | and r11, r11, #0xf800 @ pack pixel | ||
440 | and r7, r7, #0x7e00 @ r0 = pixel = (r & 0xf800) | | ||
441 | orr r11, r11, r7, lsr #4 @ ((g & 0x7e00) >> 4) | | ||
442 | orr r0, r11, r0, lsr #10 @ (b >> 10) | ||
443 | strh r0, [r3, #0x10] @ write pixel | ||
444 | 1: @ busy @ | ||
445 | ldr r7, [r3,#0xc] @ r7 = DBOP_STATUS | ||
446 | tst r7, #DBOP_BUSY @ fifo not empty? | ||
447 | beq 1b @ | ||
448 | @ | ||
449 | sub r7, r12, #16 @ r7 = Y = (Y' - 16)*149 | ||
450 | add r12, r7, r7, asl #2 @ | ||
451 | add r12, r12, r12, asl #4 @ | ||
452 | add r7, r12, r7, asl #6 @ | ||
453 | @ compute R, G, and B | ||
454 | add r0, r8, r7 @ r0 = b' = Y + bu | ||
455 | add r11, r9, r7, asl #1 @ r11 = r' = Y*2 + rv | ||
456 | rsb r7, r10, r7 @ r7 = g' = Y + guv | ||
457 | @ | ||
458 | sub r12, r0, r0, lsr #5 @ r0 = 31/32*b + b/256 | ||
459 | add r0, r12, r0, lsr #8 @ | ||
460 | @ | ||
461 | sub r12, r11, r11, lsr #5 @ r11 = 31/32*r + r/256 | ||
462 | add r11, r12, r11, lsr #8 @ | ||
463 | @ | ||
464 | sub r12, r7, r7, lsr #6 @ r7 = 63/64*g + g/256 | ||
465 | add r7, r12, r7, lsr #8 @ | ||
466 | @ | ||
467 | @ This element is zero - use r14 @ | ||
468 | @ | ||
469 | add r0, r0, r14 @ b = r0 + delta | ||
470 | add r11, r11, r14, lsl #1 @ r = r11 + delta*2 | ||
471 | add r7, r7, r14, lsr #1 @ g = r7 + delta/2 | ||
472 | @ | ||
473 | orr r12, r0, r11, asr #1 @ check if clamping is needed... | ||
474 | orr r12, r12, r7 @ ...at all | ||
475 | movs r12, r12, asr #15 @ | ||
476 | beq 15f @ no clamp @ | ||
477 | movs r12, r0, asr #15 @ clamp b | ||
478 | mvnne r0, r12, lsr #15 @ | ||
479 | andne r0, r0, #0x7c00 @ mask b only if clamped | ||
480 | movs r12, r11, asr #16 @ clamp r | ||
481 | mvnne r11, r12, lsr #16 @ | ||
482 | movs r12, r7, asr #15 @ clamp g | ||
483 | mvnne r7, r12, lsr #15 @ | ||
484 | 15: @ no clamp @ | ||
485 | @ | ||
486 | and r11, r11, #0xf800 @ pack pixel | ||
487 | and r7, r7, #0x7e00 @ r0 = pixel = (r & 0xf800) | | ||
488 | orr r11, r11, r7, lsr #4 @ ((g & 0x7e00) >> 4) | | ||
489 | orr r0, r11, r0, lsr #10 @ (b >> 10) | ||
490 | strh r0, [r3, #0x10] @ write pixel | ||
491 | 1: @ busy @ | ||
492 | ldr r7, [r3,#0xc] @ r7 = DBOP_STATUS | ||
493 | tst r7, #DBOP_BUSY @ fifo not empty? | ||
494 | beq 1b @ | ||
495 | @ | ||
496 | subs r1, r1, #2 @ subtract block from width | ||
497 | bgt 10b @ loop line @ | ||
498 | @ | ||
499 | ldmfd sp!, { r4-r12, pc } @ restore registers and return | ||
500 | .ltorg @ dump constant pool | ||
501 | .size lcd_write_yuv420_lines_odither, .-lcd_write_yuv420_lines_odither | ||
diff --git a/firmware/target/arm/as3525/sansa-e200v2/lcd-e200v2.c b/firmware/target/arm/as3525/sansa-e200v2/lcd-e200v2.c index 30ba8911ea..ef21893494 100644 --- a/firmware/target/arm/as3525/sansa-e200v2/lcd-e200v2.c +++ b/firmware/target/arm/as3525/sansa-e200v2/lcd-e200v2.c | |||
@@ -74,7 +74,7 @@ static volatile bool lcd_busy = false; | |||
74 | #define R_GAMMA_GRAD_ADJ_NEG 0x37 | 74 | #define R_GAMMA_GRAD_ADJ_NEG 0x37 |
75 | 75 | ||
76 | #define R_GAMMA_AMP_ADJ_RES_POS 0x38 | 76 | #define R_GAMMA_AMP_ADJ_RES_POS 0x38 |
77 | #define R_GAMMA_AMP_AVG_ADJ_RES_NEG 0x39 | 77 | #define R_GAMMA_AMP_AVG_ADJ_RES_NEG 0x39 |
78 | 78 | ||
79 | #define R_GATE_SCAN_POS 0x40 | 79 | #define R_GATE_SCAN_POS 0x40 |
80 | #define R_VERT_SCROLL_CONTROL 0x41 | 80 | #define R_VERT_SCROLL_CONTROL 0x41 |
@@ -89,6 +89,7 @@ static volatile bool lcd_busy = false; | |||
89 | static unsigned short r_entry_mode = R_ENTRY_MODE_HORZ_NORMAL; | 89 | static unsigned short r_entry_mode = R_ENTRY_MODE_HORZ_NORMAL; |
90 | #define R_ENTRY_MODE_VERT 0x7038 | 90 | #define R_ENTRY_MODE_VERT 0x7038 |
91 | #define R_ENTRY_MODE_SOLID_VERT 0x1038 | 91 | #define R_ENTRY_MODE_SOLID_VERT 0x1038 |
92 | #define R_ENTRY_MODE_VIDEO 0x7020 | ||
92 | 93 | ||
93 | 94 | ||
94 | /* Reverse Flag */ | 95 | /* Reverse Flag */ |
@@ -182,7 +183,7 @@ void lcd_set_invert_display(bool yesno) | |||
182 | void lcd_set_flip(bool yesno) | 183 | void lcd_set_flip(bool yesno) |
183 | { | 184 | { |
184 | display_flipped = yesno; | 185 | display_flipped = yesno; |
185 | 186 | ||
186 | r_entry_mode = yesno ? R_ENTRY_MODE_HORZ_FLIPPED : | 187 | r_entry_mode = yesno ? R_ENTRY_MODE_HORZ_FLIPPED : |
187 | R_ENTRY_MODE_HORZ_NORMAL; | 188 | R_ENTRY_MODE_HORZ_NORMAL; |
188 | } | 189 | } |
@@ -253,13 +254,13 @@ static void _display_on(void) | |||
253 | /* DC12-10 = 000b: Step-up1 = clock/8, | 254 | /* DC12-10 = 000b: Step-up1 = clock/8, |
254 | * DC02-00 = 000b: Step-up2 = clock/16, | 255 | * DC02-00 = 000b: Step-up2 = clock/16, |
255 | * VC2-0 = 010b: VciOUT = 0.87 * VciLVL */ | 256 | * VC2-0 = 010b: VciOUT = 0.87 * VciLVL */ |
256 | lcd_write_reg(R_POWER_CONTROL2, 0x0002); | 257 | lcd_write_reg(R_POWER_CONTROL2, 0x0002); |
257 | 258 | ||
258 | /* VRH3-0 = 1000b: Vreg1OUT = REGP * 1.90 */ | 259 | /* VRH3-0 = 1000b: Vreg1OUT = REGP * 1.90 */ |
259 | lcd_write_reg(R_POWER_CONTROL3, 0x0008); | 260 | lcd_write_reg(R_POWER_CONTROL3, 0x0008); |
260 | 261 | ||
261 | lcd_delay(40); | 262 | lcd_delay(40); |
262 | 263 | ||
263 | lcd_write_reg(R_POWER_CONTROL4, 0x0000); /* VCOMG = 0 */ | 264 | lcd_write_reg(R_POWER_CONTROL4, 0x0000); /* VCOMG = 0 */ |
264 | 265 | ||
265 | /* This register is unknown */ | 266 | /* This register is unknown */ |
@@ -270,8 +271,8 @@ static void _display_on(void) | |||
270 | 271 | ||
271 | lcd_delay(10); | 272 | lcd_delay(10); |
272 | 273 | ||
273 | lcd_write_reg(R_POWER_CONTROL2, 0x0000); | 274 | lcd_write_reg(R_POWER_CONTROL2, 0x0000); |
274 | lcd_write_reg(R_POWER_CONTROL3, 0x0013); | 275 | lcd_write_reg(R_POWER_CONTROL3, 0x0013); |
275 | 276 | ||
276 | lcd_delay(20); | 277 | lcd_delay(20); |
277 | 278 | ||
@@ -296,7 +297,7 @@ static void _display_on(void) | |||
296 | lcd_write_reg(R_GATE_SCAN_POS, 0); | 297 | lcd_write_reg(R_GATE_SCAN_POS, 0); |
297 | lcd_write_reg(R_VERT_SCROLL_CONTROL, 0); | 298 | lcd_write_reg(R_VERT_SCROLL_CONTROL, 0); |
298 | 299 | ||
299 | lcd_window(0, 0, LCD_WIDTH-1, LCD_HEIGHT-1); | 300 | lcd_window(0, 0, LCD_WIDTH-1, LCD_HEIGHT-1); |
300 | lcd_write_reg(R_1ST_SCR_DRV_POS, (LCD_HEIGHT-1) << 8); | 301 | lcd_write_reg(R_1ST_SCR_DRV_POS, (LCD_HEIGHT-1) << 8); |
301 | lcd_write_reg(R_2ND_SCR_DRV_POS, (LCD_HEIGHT-1) << 8); | 302 | lcd_write_reg(R_2ND_SCR_DRV_POS, (LCD_HEIGHT-1) << 8); |
302 | 303 | ||
@@ -356,6 +357,30 @@ bool lcd_active(void) | |||
356 | 357 | ||
357 | /*** update functions ***/ | 358 | /*** update functions ***/ |
358 | 359 | ||
360 | static unsigned lcd_yuv_options SHAREDBSS_ATTR = 0; | ||
361 | |||
362 | /* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */ | ||
363 | extern void lcd_write_yuv420_lines(unsigned char const * const src[3], | ||
364 | int width, | ||
365 | int stride); | ||
366 | extern void lcd_write_yuv420_lines_odither(unsigned char const * const src[3], | ||
367 | int width, | ||
368 | int stride, | ||
369 | int x_screen, /* To align dither pattern */ | ||
370 | int y_screen); | ||
371 | |||
372 | void lcd_yuv_set_options(unsigned options) | ||
373 | { | ||
374 | lcd_yuv_options = options; | ||
375 | } | ||
376 | |||
377 | static void lcd_window_blit(int xmin, int ymin, int xmax, int ymax) | ||
378 | { | ||
379 | lcd_write_reg(R_HORIZ_RAM_ADDR_POS, ((LCD_WIDTH-1 - xmin) << 8) | (LCD_WIDTH-1 - xmax)); | ||
380 | lcd_write_reg(R_VERT_RAM_ADDR_POS, (ymax << 8) | ymin); | ||
381 | lcd_write_reg(R_RAM_ADDR_SET, (ymin << 8) | (LCD_WIDTH-1 - xmin)); | ||
382 | } | ||
383 | |||
359 | /* Performance function to blit a YUV bitmap directly to the LCD | 384 | /* Performance function to blit a YUV bitmap directly to the LCD |
360 | * src_x, src_y, width and height should be even | 385 | * src_x, src_y, width and height should be even |
361 | * x, y, width and height have to be within LCD bounds | 386 | * x, y, width and height have to be within LCD bounds |
@@ -364,14 +389,58 @@ void lcd_blit_yuv(unsigned char * const src[3], | |||
364 | int src_x, int src_y, int stride, | 389 | int src_x, int src_y, int stride, |
365 | int x, int y, int width, int height) | 390 | int x, int y, int width, int height) |
366 | { | 391 | { |
367 | (void)src; | 392 | unsigned char const * yuv_src[3]; |
368 | (void)src_x; | 393 | off_t z; |
369 | (void)src_y; | 394 | |
370 | (void)stride; | 395 | lcd_busy = true; |
371 | (void)x; | 396 | |
372 | (void)y; | 397 | /* Sorry, but width and height must be >= 2 or else */ |
373 | (void)width; | 398 | width &= ~1; |
374 | (void)height; | 399 | height >>= 1; |
400 | |||
401 | z = stride*src_y; | ||
402 | yuv_src[0] = src[0] + z + src_x; | ||
403 | yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1); | ||
404 | yuv_src[2] = src[2] + (yuv_src[1] - src[1]); | ||
405 | |||
406 | lcd_write_reg(R_ENTRY_MODE, R_ENTRY_MODE_VIDEO); | ||
407 | |||
408 | if (lcd_yuv_options & LCD_YUV_DITHER) | ||
409 | { | ||
410 | do | ||
411 | { | ||
412 | lcd_window_blit(y, x, y+1, x+width-1); | ||
413 | |||
414 | /* Start write to GRAM */ | ||
415 | lcd_write_cmd(R_WRITE_DATA_2_GRAM); | ||
416 | |||
417 | lcd_write_yuv420_lines_odither(yuv_src, width, stride, x, y); | ||
418 | yuv_src[0] += stride << 1; /* Skip down two luma lines */ | ||
419 | yuv_src[1] += stride >> 1; /* Skip down one chroma line */ | ||
420 | yuv_src[2] += stride >> 1; | ||
421 | y+=2; | ||
422 | } | ||
423 | while (--height > 0); | ||
424 | } | ||
425 | else | ||
426 | { | ||
427 | do | ||
428 | { | ||
429 | lcd_window_blit(y, x, y+1, x+width-1); | ||
430 | |||
431 | /* Start write to GRAM */ | ||
432 | lcd_write_cmd(R_WRITE_DATA_2_GRAM); | ||
433 | |||
434 | lcd_write_yuv420_lines(yuv_src, width, stride); | ||
435 | yuv_src[0] += stride << 1; /* Skip down two luma lines */ | ||
436 | yuv_src[1] += stride >> 1; /* Skip down one chroma line */ | ||
437 | yuv_src[2] += stride >> 1; | ||
438 | y+=2; | ||
439 | } | ||
440 | while (--height > 0); | ||
441 | } | ||
442 | |||
443 | lcd_busy = false; | ||
375 | } | 444 | } |
376 | 445 | ||
377 | /* Update the display. | 446 | /* Update the display. |
diff --git a/firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c b/firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c index 3e08ba4dff..141b890861 100644 --- a/firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c +++ b/firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c | |||
@@ -37,7 +37,9 @@ | |||
37 | #define R_WRITE_DATA_2_GRAM 0x22 | 37 | #define R_WRITE_DATA_2_GRAM 0x22 |
38 | 38 | ||
39 | #define R_ENTRY_MODE_HORZ 0x7030 | 39 | #define R_ENTRY_MODE_HORZ 0x7030 |
40 | #define R_ENTRY_MODE_VERT 0x7038 | ||
40 | 41 | ||
42 | static unsigned lcd_yuv_options SHAREDBSS_ATTR = 0; | ||
41 | static bool display_on = false; /* is the display turned on? */ | 43 | static bool display_on = false; /* is the display turned on? */ |
42 | static bool display_flipped = false; | 44 | static bool display_flipped = false; |
43 | static int xoffset = 20; /* needed for flip */ | 45 | static int xoffset = 20; /* needed for flip */ |
@@ -189,7 +191,7 @@ void lcd_enable(bool on) | |||
189 | * avoid irritating flash on backlight on */ | 191 | * avoid irritating flash on backlight on */ |
190 | while(delay--); | 192 | while(delay--); |
191 | lcd_activation_call_hook(); | 193 | lcd_activation_call_hook(); |
192 | 194 | ||
193 | } | 195 | } |
194 | else | 196 | else |
195 | { | 197 | { |
@@ -210,22 +212,94 @@ bool lcd_active(void) | |||
210 | 212 | ||
211 | /*** update functions ***/ | 213 | /*** update functions ***/ |
212 | 214 | ||
213 | /* Performance function to blit a YUV bitmap directly to the LCD | 215 | /* Set horizontal window addresses */ |
214 | * src_x, src_y, width and height should be even | 216 | static void lcd_window_x(int xmin, int xmax) |
215 | * x, y, width and height have to be within LCD bounds | 217 | { |
216 | */ | 218 | xmin += xoffset; |
219 | xmax += xoffset; | ||
220 | lcd_write_reg(0x46, (xmax << 8) | xmin); | ||
221 | lcd_write_reg(0x20, xmin); | ||
222 | } | ||
223 | |||
224 | /* Set vertical window addresses */ | ||
225 | static void lcd_window_y(int ymin, int ymax) | ||
226 | { | ||
227 | lcd_write_reg(0x47, ymax); | ||
228 | lcd_write_reg(0x48, ymin); | ||
229 | lcd_write_reg(0x21, ymin); | ||
230 | } | ||
231 | |||
232 | void lcd_yuv_set_options(unsigned options) | ||
233 | { | ||
234 | lcd_yuv_options = options; | ||
235 | } | ||
236 | |||
237 | /* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */ | ||
238 | extern void lcd_write_yuv420_lines(unsigned char const * const src[3], | ||
239 | int width, | ||
240 | int stride); | ||
241 | extern void lcd_write_yuv420_lines_odither(unsigned char const * const src[3], | ||
242 | int width, | ||
243 | int stride, | ||
244 | int x_screen, /* To align dither pattern */ | ||
245 | int y_screen); | ||
246 | /* Performance function to blit a YUV bitmap directly to the LCD */ | ||
217 | void lcd_blit_yuv(unsigned char * const src[3], | 247 | void lcd_blit_yuv(unsigned char * const src[3], |
218 | int src_x, int src_y, int stride, | 248 | int src_x, int src_y, int stride, |
219 | int x, int y, int width, int height) | 249 | int x, int y, int width, int height) |
220 | { | 250 | { |
221 | (void)src; | 251 | unsigned char const * yuv_src[3]; |
222 | (void)src_x; | 252 | off_t z; |
223 | (void)src_y; | 253 | |
224 | (void)stride; | 254 | lcd_busy = true; |
225 | (void)x; | 255 | |
226 | (void)y; | 256 | lcd_write_reg(R_ENTRY_MODE, R_ENTRY_MODE_VERT); |
227 | (void)width; | 257 | |
228 | (void)height; | 258 | /* Sorry, but width and height must be >= 2 or else */ |
259 | width &= ~1; | ||
260 | height >>= 1; | ||
261 | |||
262 | z = stride*src_y; | ||
263 | yuv_src[0] = src[0] + z + src_x; | ||
264 | yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1); | ||
265 | yuv_src[2] = src[2] + (yuv_src[1] - src[1]); | ||
266 | |||
267 | lcd_window_x(x, x + width - 1); | ||
268 | |||
269 | if (lcd_yuv_options & LCD_YUV_DITHER) | ||
270 | { | ||
271 | do | ||
272 | { | ||
273 | lcd_window_y(y, y + 1); | ||
274 | /* Start write to GRAM */ | ||
275 | lcd_write_cmd(R_WRITE_DATA_2_GRAM); | ||
276 | |||
277 | lcd_write_yuv420_lines_odither(yuv_src, width, stride, x, y); | ||
278 | yuv_src[0] += stride << 1; /* Skip down two luma lines */ | ||
279 | yuv_src[1] += stride >> 1; /* Skip down one chroma line */ | ||
280 | yuv_src[2] += stride >> 1; | ||
281 | y += 2; | ||
282 | } | ||
283 | while (--height > 0); | ||
284 | } | ||
285 | else | ||
286 | { | ||
287 | do | ||
288 | { | ||
289 | lcd_window_y(y, y + 1); | ||
290 | /* Start write to GRAM */ | ||
291 | lcd_write_cmd(R_WRITE_DATA_2_GRAM); | ||
292 | |||
293 | lcd_write_yuv420_lines(yuv_src, width, stride); | ||
294 | yuv_src[0] += stride << 1; /* Skip down two luma lines */ | ||
295 | yuv_src[1] += stride >> 1; /* Skip down one chroma line */ | ||
296 | yuv_src[2] += stride >> 1; | ||
297 | y += 2; | ||
298 | } | ||
299 | while (--height > 0); | ||
300 | } | ||
301 | |||
302 | lcd_busy = false; | ||
229 | } | 303 | } |
230 | 304 | ||
231 | void lcd_init_device() | 305 | void lcd_init_device() |
@@ -242,23 +316,6 @@ void lcd_init_device() | |||
242 | _display_on(); | 316 | _display_on(); |
243 | } | 317 | } |
244 | 318 | ||
245 | /* Set horizontal window addresses */ | ||
246 | void lcd_window_x(int xmin, int xmax) | ||
247 | { | ||
248 | xmin += xoffset; | ||
249 | xmax += xoffset; | ||
250 | lcd_write_reg(0x46, (xmax << 8) | xmin); | ||
251 | lcd_write_reg(0x20, xmin); | ||
252 | } | ||
253 | |||
254 | /* Set vertical window addresses */ | ||
255 | void lcd_window_y(int ymin, int ymax) | ||
256 | { | ||
257 | lcd_write_reg(0x47, ymax); | ||
258 | lcd_write_reg(0x48, ymin); | ||
259 | lcd_write_reg(0x21, ymin); | ||
260 | } | ||
261 | |||
262 | /* Update the display. | 319 | /* Update the display. |
263 | This must be called after all other LCD functions that change the display. */ | 320 | This must be called after all other LCD functions that change the display. */ |
264 | void lcd_update(void) | 321 | void lcd_update(void) |
@@ -272,7 +329,7 @@ void lcd_update(void) | |||
272 | lcd_window_x(0, LCD_WIDTH - 1); | 329 | lcd_window_x(0, LCD_WIDTH - 1); |
273 | lcd_window_y(0, LCD_HEIGHT - 1); | 330 | lcd_window_y(0, LCD_HEIGHT - 1); |
274 | 331 | ||
275 | /* Start write to GRAM */ | 332 | /* Start write to GRAM */ |
276 | lcd_write_cmd(R_WRITE_DATA_2_GRAM); | 333 | lcd_write_cmd(R_WRITE_DATA_2_GRAM); |
277 | 334 | ||
278 | /* Write data */ | 335 | /* Write data */ |
@@ -313,7 +370,7 @@ void lcd_update_rect(int x, int y, int width, int height) | |||
313 | lcd_window_x(x, xmax); | 370 | lcd_window_x(x, xmax); |
314 | lcd_window_y(y, ymax); | 371 | lcd_window_y(y, ymax); |
315 | 372 | ||
316 | /* Start write to GRAM */ | 373 | /* Start write to GRAM */ |
317 | lcd_write_cmd(R_WRITE_DATA_2_GRAM); | 374 | lcd_write_cmd(R_WRITE_DATA_2_GRAM); |
318 | 375 | ||
319 | ptr = (unsigned short *)&lcd_framebuffer[y][x]; | 376 | ptr = (unsigned short *)&lcd_framebuffer[y][x]; |