summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2007-09-25 02:59:42 +0000
committerMichael Sevakis <jethead71@rockbox.org>2007-09-25 02:59:42 +0000
commit287d6223d3e4f90043e5fd36cf49d7267b53023d (patch)
tree04771c28f2b826099805f5a5ad98b8c4e41091cc
parent24327ddf7ba62c873bd392fa5abe5c341b4a47b9 (diff)
downloadrockbox-287d6223d3e4f90043e5fd36cf49d7267b53023d.tar.gz
rockbox-287d6223d3e4f90043e5fd36cf49d7267b53023d.zip
Dithering option for mpegplayer on gigabeat-f/x and e200. Assembly IDCT for ARm just to make it all work more nicely. Move UI simulator YUV code to its core to adapt it.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14851 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/plugin.c6
-rw-r--r--apps/plugin.h8
-rw-r--r--apps/plugins/mpegplayer/SOURCES3
-rw-r--r--apps/plugins/mpegplayer/mpeg_settings.c106
-rw-r--r--apps/plugins/mpegplayer/mpeg_settings.h3
-rw-r--r--apps/plugins/mpegplayer/video_out_rockbox.c204
-rw-r--r--firmware/SOURCES4
-rw-r--r--firmware/export/lcd.h4
-rw-r--r--firmware/target/arm/lcd-as-memframe.S554
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/lcd-as-meg-fx.S279
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c45
-rw-r--r--firmware/target/arm/sandisk/sansa-e200/lcd-as-e200.S279
-rw-r--r--firmware/target/arm/sandisk/sansa-e200/lcd-e200.c45
-rw-r--r--uisimulator/sdl/lcd-bitmap.c204
14 files changed, 935 insertions, 809 deletions
diff --git a/apps/plugin.c b/apps/plugin.c
index bdb59e6005..f56d532537 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -179,7 +179,7 @@ static const struct plugin_api rockbox_api = {
179 lcd_remote_bitmap, 179 lcd_remote_bitmap,
180#endif 180#endif
181 181
182#if defined(HAVE_LCD_COLOR) && !defined(SIMULATOR) 182#if defined(HAVE_LCD_COLOR)
183 lcd_yuv_blit, 183 lcd_yuv_blit,
184#endif 184#endif
185 /* list */ 185 /* list */
@@ -505,6 +505,10 @@ static const struct plugin_api rockbox_api = {
505 get_metadata, 505 get_metadata,
506#endif 506#endif
507 led, 507 led,
508
509#if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200)
510 lcd_yuv_set_options,
511#endif
508}; 512};
509 513
510int plugin_load(const char* plugin, void* parameter) 514int plugin_load(const char* plugin, void* parameter)
diff --git a/apps/plugin.h b/apps/plugin.h
index c7049c7fd0..a2e24f88d9 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -112,7 +112,7 @@
112#define PLUGIN_MAGIC 0x526F634B /* RocK */ 112#define PLUGIN_MAGIC 0x526F634B /* RocK */
113 113
114/* increase this every time the api struct changes */ 114/* increase this every time the api struct changes */
115#define PLUGIN_API_VERSION 76 115#define PLUGIN_API_VERSION 77
116 116
117/* update this to latest version if a change to the api struct breaks 117/* update this to latest version if a change to the api struct breaks
118 backwards compatibility (and please take the opportunity to sort in any 118 backwards compatibility (and please take the opportunity to sort in any
@@ -259,7 +259,7 @@ struct plugin_api {
259 void (*lcd_remote_bitmap)(const fb_remote_data *src, int x, int y, int width, 259 void (*lcd_remote_bitmap)(const fb_remote_data *src, int x, int y, int width,
260 int height); 260 int height);
261#endif 261#endif
262#if defined(HAVE_LCD_COLOR) && !defined(SIMULATOR) 262#if defined(HAVE_LCD_COLOR)
263 void (*lcd_yuv_blit)(unsigned char * const src[3], 263 void (*lcd_yuv_blit)(unsigned char * const src[3],
264 int src_x, int src_y, int stride, 264 int src_x, int src_y, int stride,
265 int x, int y, int width, int height); 265 int x, int y, int width, int height);
@@ -623,6 +623,10 @@ struct plugin_api {
623 bool (*get_metadata)(struct mp3entry* id3, int fd, const char* trackname); 623 bool (*get_metadata)(struct mp3entry* id3, int fd, const char* trackname);
624#endif 624#endif
625 void (*led)(bool on); 625 void (*led)(bool on);
626
627#if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200)
628 void (*lcd_yuv_set_options)(unsigned options);
629#endif
626}; 630};
627 631
628/* plugin header */ 632/* plugin header */
diff --git a/apps/plugins/mpegplayer/SOURCES b/apps/plugins/mpegplayer/SOURCES
index e9a01b73d0..6629cf7a4c 100644
--- a/apps/plugins/mpegplayer/SOURCES
+++ b/apps/plugins/mpegplayer/SOURCES
@@ -1,14 +1,15 @@
1alloc.c 1alloc.c
2decode.c 2decode.c
3header.c 3header.c
4idct.c
5 4
6motion_comp.c 5motion_comp.c
7 6
8#ifdef CPU_ARM 7#ifdef CPU_ARM
8idct_arm_c.c
9motion_comp_arm_c.c 9motion_comp_arm_c.c
10motion_comp_arm_s.S 10motion_comp_arm_s.S
11#else /* other CPU or SIM */ 11#else /* other CPU or SIM */
12idct.c
12motion_comp_c.c 13motion_comp_c.c
13#endif /* CPU_* */ 14#endif /* CPU_* */
14 15
diff --git a/apps/plugins/mpegplayer/mpeg_settings.c b/apps/plugins/mpegplayer/mpeg_settings.c
index 964bad08bd..28062f4567 100644
--- a/apps/plugins/mpegplayer/mpeg_settings.c
+++ b/apps/plugins/mpegplayer/mpeg_settings.c
@@ -9,41 +9,87 @@ extern struct plugin_api* rb;
9struct mpeg_settings settings; 9struct mpeg_settings settings;
10static struct mpeg_settings old_settings; 10static struct mpeg_settings old_settings;
11 11
12#define SETTINGS_VERSION 1 12#define SETTINGS_VERSION 2
13#define SETTINGS_MIN_VERSION 1 13#define SETTINGS_MIN_VERSION 1
14#define SETTINGS_FILENAME "mpegplayer.cfg" 14#define SETTINGS_FILENAME "mpegplayer.cfg"
15 15
16static char* showfps_options[] = {"No", "Yes"};
17static char* limitfps_options[] = {"No", "Yes"};
18static char* skipframes_options[] = {"No", "Yes"};
19
20static struct configdata config[] = 16static struct configdata config[] =
21{ 17{
22 {TYPE_ENUM, 0, 2, &settings.showfps, "Show FPS", showfps_options, NULL}, 18 {TYPE_ENUM, 0, 2, &settings.showfps, "Show FPS",
23 {TYPE_ENUM, 0, 2, &settings.limitfps, "Limit FPS", limitfps_options, NULL}, 19 (char *[]){ "No", "Yes" }, NULL},
24 {TYPE_ENUM, 0, 2, &settings.skipframes, "Skip frames", skipframes_options, NULL}, 20 {TYPE_ENUM, 0, 2, &settings.limitfps, "Limit FPS",
21 (char *[]){ "No", "Yes" }, NULL},
22 {TYPE_ENUM, 0, 2, &settings.skipframes, "Skip frames",
23 (char *[]){ "No", "Yes" }, NULL},
24#if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200)
25 {TYPE_INT, 0, INT_MAX, &settings.displayoptions, "Display options",
26 NULL, NULL},
27#endif
28};
29
30enum mpeg_menu_ids
31{
32 __MPEG_OPTION_START = -1,
33#if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200)
34 MPEG_OPTION_DISPLAY_SETTINGS,
35#endif
36 MPEG_OPTION_DISPLAY_FPS,
37 MPEG_OPTION_LIMIT_FPS,
38 MPEG_OPTION_SKIP_FRAMES,
39 MPEG_OPTION_QUIT,
40};
41
42static const struct opt_items noyes[2] = {
43 { "No", -1 },
44 { "Yes", -1 },
25}; 45};
26 46
47#if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200)
48static bool set_option_dithering(void)
49{
50 int val = (settings.displayoptions & LCD_YUV_DITHER) ? 1 : 0;
51 rb->set_option("Dithering", &val, INT, noyes, 2, NULL);
52 settings.displayoptions = (settings.displayoptions & ~LCD_YUV_DITHER)
53 | ((val != 0) ? LCD_YUV_DITHER : 0);
54 rb->lcd_yuv_set_options(settings.displayoptions);
55 return false;
56}
57
58static void display_options(void)
59{
60 static const struct menu_item items[] = {
61 { "Dithering", set_option_dithering },
62 };
63
64 int m = menu_init(rb, items, ARRAYLEN(items),
65 NULL, NULL, NULL, NULL);
66 menu_run(m);
67 menu_exit(m);
68}
69#endif /* #ifdef TOSHIBA_GIGABEAT_F */
70
27bool mpeg_menu(void) 71bool mpeg_menu(void)
28{ 72{
29 int m; 73 int m;
30 int result; 74 int result;
31 int menu_quit=0; 75 int menu_quit=0;
32 76
33 static const struct opt_items noyes[2] = {
34 { "No", -1 },
35 { "Yes", -1 },
36 };
37
38 static const struct menu_item items[] = { 77 static const struct menu_item items[] = {
39 { "Display FPS", NULL }, 78#if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200)
40 { "Limit FPS", NULL }, 79 [MPEG_OPTION_DISPLAY_SETTINGS] =
41 { "Skip frames", NULL }, 80 { "Display Options", NULL },
42 { "Quit mpegplayer", NULL }, 81#endif
82 [MPEG_OPTION_DISPLAY_FPS] =
83 { "Display FPS", NULL },
84 [MPEG_OPTION_LIMIT_FPS] =
85 { "Limit FPS", NULL },
86 [MPEG_OPTION_SKIP_FRAMES] =
87 { "Skip frames", NULL },
88 [MPEG_OPTION_QUIT] =
89 { "Quit mpegplayer", NULL },
43 }; 90 };
44 91
45 m = menu_init(rb, items, sizeof(items) / sizeof(*items), 92 m = menu_init(rb, items, ARRAYLEN(items), NULL, NULL, NULL, NULL);
46 NULL, NULL, NULL, NULL);
47 93
48 rb->button_clear_queue(); 94 rb->button_clear_queue();
49 95
@@ -52,22 +98,28 @@ bool mpeg_menu(void)
52 98
53 switch(result) 99 switch(result)
54 { 100 {
55 case 0: /* Show FPS */ 101#if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200)
102 case MPEG_OPTION_DISPLAY_SETTINGS:
103 display_options();
104 break;
105#endif
106 case MPEG_OPTION_DISPLAY_FPS:
56 rb->set_option("Display FPS",&settings.showfps,INT, 107 rb->set_option("Display FPS",&settings.showfps,INT,
57 noyes, 2, NULL); 108 noyes, 2, NULL);
58 break; 109 break;
59 case 1: /* Limit FPS */ 110 case MPEG_OPTION_LIMIT_FPS:
60 rb->set_option("Limit FPS",&settings.limitfps,INT, 111 rb->set_option("Limit FPS",&settings.limitfps,INT,
61 noyes, 2, NULL); 112 noyes, 2, NULL);
62 break; 113 break;
63 case 2: /* Skip frames */ 114 case MPEG_OPTION_SKIP_FRAMES:
64 rb->set_option("Skip frames",&settings.skipframes,INT, 115 rb->set_option("Skip frames",&settings.skipframes,INT,
65 noyes, 2, NULL); 116 noyes, 2, NULL);
66 break; 117 break;
118 case MPEG_OPTION_QUIT:
67 default: 119 default:
68 menu_quit=1; 120 menu_quit=1;
69 if (result == MENU_ATTACHED_USB) 121 if (result == MENU_ATTACHED_USB)
70 result = 3; 122 result = MPEG_OPTION_QUIT;
71 break; 123 break;
72 } 124 }
73 } 125 }
@@ -77,7 +129,7 @@ bool mpeg_menu(void)
77 rb->lcd_clear_display(); 129 rb->lcd_clear_display();
78 rb->lcd_update(); 130 rb->lcd_update();
79 131
80 return (result==3); 132 return (result==MPEG_OPTION_QUIT);
81} 133}
82 134
83 135
@@ -87,6 +139,9 @@ void init_settings(void)
87 settings.showfps = 0; /* Do not show FPS */ 139 settings.showfps = 0; /* Do not show FPS */
88 settings.limitfps = 1; /* Limit FPS */ 140 settings.limitfps = 1; /* Limit FPS */
89 settings.skipframes = 1; /* Skip frames */ 141 settings.skipframes = 1; /* Skip frames */
142#if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200)
143 settings.displayoptions = 0; /* No visual effects */
144#endif
90 145
91 configfile_init(rb); 146 configfile_init(rb);
92 147
@@ -105,6 +160,9 @@ void init_settings(void)
105 /* Keep a copy of the saved version of the settings - so we can check if 160 /* Keep a copy of the saved version of the settings - so we can check if
106 the settings have changed when we quit */ 161 the settings have changed when we quit */
107 old_settings = settings; 162 old_settings = settings;
163#if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200)
164 rb->lcd_yuv_set_options(settings.displayoptions);
165#endif
108} 166}
109 167
110void save_settings(void) 168void save_settings(void)
diff --git a/apps/plugins/mpegplayer/mpeg_settings.h b/apps/plugins/mpegplayer/mpeg_settings.h
index cd2dcd2343..7721c46f64 100644
--- a/apps/plugins/mpegplayer/mpeg_settings.h
+++ b/apps/plugins/mpegplayer/mpeg_settings.h
@@ -5,6 +5,9 @@ struct mpeg_settings {
5 int showfps; 5 int showfps;
6 int limitfps; 6 int limitfps;
7 int skipframes; 7 int skipframes;
8#if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200)
9 unsigned displayoptions;
10#endif
8}; 11};
9 12
10extern struct mpeg_settings settings; 13extern struct mpeg_settings settings;
diff --git a/apps/plugins/mpegplayer/video_out_rockbox.c b/apps/plugins/mpegplayer/video_out_rockbox.c
index b57f77bc0a..2aac0b8039 100644
--- a/apps/plugins/mpegplayer/video_out_rockbox.c
+++ b/apps/plugins/mpegplayer/video_out_rockbox.c
@@ -40,216 +40,12 @@ static int output_y;
40static int output_width; 40static int output_width;
41static int output_height; 41static int output_height;
42 42
43#if defined(SIMULATOR) && defined(HAVE_LCD_COLOR)
44
45/**
46 * |R| |1.000000 -0.000001 1.402000| |Y'|
47 * |G| = |1.000000 -0.334136 -0.714136| |Pb|
48 * |B| |1.000000 1.772000 0.000000| |Pr|
49 * Scaled, normalized, rounded and tweaked to yield RGB 565:
50 * |R| |74 0 101| |Y' - 16| >> 9
51 * |G| = |74 -24 -51| |Cb - 128| >> 8
52 * |B| |74 128 0| |Cr - 128| >> 9
53 */
54#define YFAC (74)
55#define RVFAC (101)
56#define GUFAC (-24)
57#define GVFAC (-51)
58#define BUFAC (128)
59
60static inline int clamp(int val, int min, int max)
61{
62 if (val < min)
63 val = min;
64 else if (val > max)
65 val = max;
66 return val;
67}
68
69/* Draw a partial YUV colour bitmap - similiar behavior to lcd_yuv_blit
70 in the core */
71static void yuv_bitmap_part(unsigned char * const src[3],
72 int src_x, int src_y, int stride,
73 int x, int y, int width, int height)
74{
75 const unsigned char *ysrc, *usrc, *vsrc;
76 fb_data *dst, *row_end;
77 off_t z;
78
79 /* width and height must be >= 2 and an even number */
80 width &= ~1;
81 height >>= 1;
82
83#if LCD_WIDTH >= LCD_HEIGHT
84 dst = rb->lcd_framebuffer + LCD_WIDTH * y + x;
85 row_end = dst + width;
86#else
87 dst = rb->lcd_framebuffer + x * LCD_WIDTH + (LCD_WIDTH - y) - 1;
88 row_end = dst + LCD_WIDTH * width;
89#endif
90
91 z = stride * src_y;
92 ysrc = src[0] + z + src_x;
93 usrc = src[1] + (z >> 2) + (src_x >> 1);
94 vsrc = src[2] + (usrc - src[1]);
95
96 /* stride => amount to jump from end of last row to start of next */
97 stride -= width;
98
99 /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
100
101 do
102 {
103 do
104 {
105 int y, cb, cr, rv, guv, bu, r, g, b;
106
107 y = YFAC*(*ysrc++ - 16);
108 cb = *usrc++ - 128;
109 cr = *vsrc++ - 128;
110
111 rv = RVFAC*cr;
112 guv = GUFAC*cb + GVFAC*cr;
113 bu = BUFAC*cb;
114
115 r = y + rv;
116 g = y + guv;
117 b = y + bu;
118
119 if ((unsigned)(r | g | b) > 64*256-1)
120 {
121 r = clamp(r, 0, 64*256-1);
122 g = clamp(g, 0, 64*256-1);
123 b = clamp(b, 0, 64*256-1);
124 }
125
126 *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
127
128#if LCD_WIDTH >= LCD_HEIGHT
129 dst++;
130#else
131 dst += LCD_WIDTH;
132#endif
133
134 y = YFAC*(*ysrc++ - 16);
135 r = y + rv;
136 g = y + guv;
137 b = y + bu;
138
139 if ((unsigned)(r | g | b) > 64*256-1)
140 {
141 r = clamp(r, 0, 64*256-1);
142 g = clamp(g, 0, 64*256-1);
143 b = clamp(b, 0, 64*256-1);
144 }
145
146 *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
147
148#if LCD_WIDTH >= LCD_HEIGHT
149 dst++;
150#else
151 dst += LCD_WIDTH;
152#endif
153 }
154 while (dst < row_end);
155
156 ysrc += stride;
157 usrc -= width >> 1;
158 vsrc -= width >> 1;
159
160#if LCD_WIDTH >= LCD_HEIGHT
161 row_end += LCD_WIDTH;
162 dst += LCD_WIDTH - width;
163#else
164 row_end -= 1;
165 dst -= LCD_WIDTH*width + 1;
166#endif
167
168 do
169 {
170 int y, cb, cr, rv, guv, bu, r, g, b;
171
172 y = YFAC*(*ysrc++ - 16);
173 cb = *usrc++ - 128;
174 cr = *vsrc++ - 128;
175
176 rv = RVFAC*cr;
177 guv = GUFAC*cb + GVFAC*cr;
178 bu = BUFAC*cb;
179
180 r = y + rv;
181 g = y + guv;
182 b = y + bu;
183
184 if ((unsigned)(r | g | b) > 64*256-1)
185 {
186 r = clamp(r, 0, 64*256-1);
187 g = clamp(g, 0, 64*256-1);
188 b = clamp(b, 0, 64*256-1);
189 }
190
191 *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
192
193#if LCD_WIDTH >= LCD_HEIGHT
194 dst++;
195#else
196 dst += LCD_WIDTH;
197#endif
198
199 y = YFAC*(*ysrc++ - 16);
200 r = y + rv;
201 g = y + guv;
202 b = y + bu;
203
204 if ((unsigned)(r | g | b) > 64*256-1)
205 {
206 r = clamp(r, 0, 64*256-1);
207 g = clamp(g, 0, 64*256-1);
208 b = clamp(b, 0, 64*256-1);
209 }
210
211 *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
212
213#if LCD_WIDTH >= LCD_HEIGHT
214 dst++;
215#else
216 dst += LCD_WIDTH;
217#endif
218 }
219 while (dst < row_end);
220
221 ysrc += stride;
222 usrc += stride >> 1;
223 vsrc += stride >> 1;
224
225#if LCD_WIDTH >= LCD_HEIGHT
226 row_end += LCD_WIDTH;
227 dst += LCD_WIDTH - width;
228#else
229 row_end -= 1;
230 dst -= LCD_WIDTH*width + 1;
231#endif
232 }
233 while (--height > 0);
234}
235#endif /* defined(SIMULATOR) && defined(HAVE_LCD_COLOR) */
236
237void vo_draw_frame (uint8_t * const * buf) 43void vo_draw_frame (uint8_t * const * buf)
238{ 44{
239#ifdef HAVE_LCD_COLOR 45#ifdef HAVE_LCD_COLOR
240#ifdef SIMULATOR
241 yuv_bitmap_part(buf,0,0,image_width,
242 output_x,output_y,output_width,output_height);
243#if LCD_WIDTH >= LCD_HEIGHT
244 rb->lcd_update_rect(output_x,output_y,output_width,output_height);
245#else
246 rb->lcd_update_rect(output_y,output_x,output_height,output_width);
247#endif
248#else
249 rb->lcd_yuv_blit(buf, 46 rb->lcd_yuv_blit(buf,
250 0,0,image_width, 47 0,0,image_width,
251 output_x,output_y,output_width,output_height); 48 output_x,output_y,output_width,output_height);
252#endif
253#else 49#else
254 gray_ub_gray_bitmap_part(buf[0],0,0,image_width, 50 gray_ub_gray_bitmap_part(buf[0],0,0,image_width,
255 output_x,output_y,output_width,output_height); 51 output_x,output_y,output_width,output_height);
diff --git a/firmware/SOURCES b/firmware/SOURCES
index c98b44d433..45bedd9dbe 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -407,9 +407,9 @@ target/sh/archos/ondio/usb-ondio.c
407 407
408#ifdef SANSA_E200 408#ifdef SANSA_E200
409#ifndef SIMULATOR 409#ifndef SIMULATOR
410target/arm/lcd-as-memframe.S
410target/arm/sandisk/ata-c200_e200.c 411target/arm/sandisk/ata-c200_e200.c
411target/arm/sandisk/sansa-e200/lcd-e200.c 412target/arm/sandisk/sansa-e200/lcd-e200.c
412target/arm/sandisk/sansa-e200/lcd-as-e200.S
413target/arm/sandisk/adc-c200_e200.c 413target/arm/sandisk/adc-c200_e200.c
414target/arm/sandisk/backlight-c200_e200.c 414target/arm/sandisk/backlight-c200_e200.c
415target/arm/usb-fw-pp502x.c 415target/arm/usb-fw-pp502x.c
@@ -572,13 +572,13 @@ target/arm/usb-fw-pp502x.c
572 572
573#ifdef GIGABEAT_F 573#ifdef GIGABEAT_F
574#ifndef SIMULATOR 574#ifndef SIMULATOR
575target/arm/lcd-as-memframe.S
575target/arm/s3c2440/gigabeat-fx/adc-meg-fx.c 576target/arm/s3c2440/gigabeat-fx/adc-meg-fx.c
576target/arm/s3c2440/gigabeat-fx/ata-meg-fx.c 577target/arm/s3c2440/gigabeat-fx/ata-meg-fx.c
577target/arm/s3c2440/gigabeat-fx/backlight-meg-fx.c 578target/arm/s3c2440/gigabeat-fx/backlight-meg-fx.c
578target/arm/s3c2440/gigabeat-fx/button-meg-fx.c 579target/arm/s3c2440/gigabeat-fx/button-meg-fx.c
579target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.c 580target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.c
580target/arm/s3c2440/gigabeat-fx/kernel-meg-fx.c 581target/arm/s3c2440/gigabeat-fx/kernel-meg-fx.c
581target/arm/s3c2440/gigabeat-fx/lcd-as-meg-fx.S
582target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c 582target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c
583target/arm/s3c2440/gigabeat-fx/power-meg-fx.c 583target/arm/s3c2440/gigabeat-fx/power-meg-fx.c
584target/arm/s3c2440/gigabeat-fx/powermgmt-meg-fx.c 584target/arm/s3c2440/gigabeat-fx/powermgmt-meg-fx.c
diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h
index 49256ff50f..ac0aea8664 100644
--- a/firmware/export/lcd.h
+++ b/firmware/export/lcd.h
@@ -84,7 +84,9 @@ extern void lcd_puts_scroll(int x, int y, const unsigned char* string);
84extern void lcd_puts_scroll_style(int x, int y, const unsigned char* string, 84extern void lcd_puts_scroll_style(int x, int y, const unsigned char* string,
85 int style); 85 int style);
86 86
87#if defined(HAVE_LCD_COLOR) && !defined(SIMULATOR) 87#if defined(HAVE_LCD_COLOR)
88#define LCD_YUV_DITHER 0x1
89extern void lcd_yuv_set_options(unsigned options);
88extern void lcd_yuv_blit(unsigned char * const src[3], 90extern void lcd_yuv_blit(unsigned char * const src[3],
89 int src_x, int src_y, int stride, 91 int src_x, int src_y, int stride,
90 int x, int y, int width, int height); 92 int x, int y, int width, int height);
diff --git a/firmware/target/arm/lcd-as-memframe.S b/firmware/target/arm/lcd-as-memframe.S
new file mode 100644
index 0000000000..7071bec7ac
--- /dev/null
+++ b/firmware/target/arm/lcd-as-memframe.S
@@ -0,0 +1,554 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 by Michael Sevakis
11 *
12 * ARM code for memory framebuffer LCDs
13 *
14 * All files in this archive are subject to the GNU General Public License.
15 * See the file COPYING in the source tree root for full license agreement.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "config.h"
23#include "cpu.h"
24
25/****************************************************************************
26 * void lcd_copy_buffer_rect(fb_data *dst, fb_data *src, int width,
27 * int height);
28 */
29 .section .icode, "ax", %progbits
30 .align 2
31 .global lcd_copy_buffer_rect
32 .type lcd_copy_buffer_rect, %function
33 @ r0 = dst
34 @ r1 = src
35 @ r2 = width
36 @ r3 = height
37lcd_copy_buffer_rect: @
38 stmfd sp!, { r4-r12, lr } @ save non-scratch regs
39 mov r5, r2 @ r5 = cached width
40 rsb r4, r2, #LCD_WIDTH @ r4 = LCD_WIDTH - width
4110: @ copy line @
42 subs r2, r5, #1 @ r2 = width - 1
43 beq 40f @ finish line @ one halfword? skip to trailing copy
44 tst r0, #2 @ word aligned?
45 beq 20f @ rem copy @ yes? skip to word copy
46 ldrh r6, [r1], #2 @ copy leading halfword
47 subs r2, r2, #1 @
48 strh r6, [r0], #2 @
49 ble 40f @ finish line @ next line if lt or finish
50 @ trailing halfword if eq
5120: @ rem copy @
52 add r14, r2, #1 @ get remaining width mod 16 after word
53 @ align (rw)
54 and r14, r14, #0xe @ r14 = 0 (16), 2, 4, 6, 8, 10, 12, 14
55 add pc, pc, r14, lsl #3 @ branch to 32-byte align
56 nop @
57 b 30f @ rw % 16 = 0 or 1? use octword loop
58 nop @
59 nop @
60 nop @
61 ldr r6, [r1], #4 @ rw % 16 = 2 or 3
62 subs r2, r2, #2 @
63 str r6, [r0], #4 @
64 b 25f @ copy up done @
65 ldmia r1!, { r6-r7 } @ rw % 16 = 4 or 5
66 subs r2, r2, #4 @
67 stmia r0!, { r6-r7 } @
68 b 25f @ copy up done @
69 ldmia r1!, { r6-r8 } @ rw % 16 = 6 or 7
70 subs r2, r2, #6 @
71 stmia r0!, { r6-r8 } @
72 b 25f @ copy up done @
73 ldmia r1!, { r6-r9 } @ rw % 16 = 8 or 9
74 subs r2, r2, #8 @
75 stmia r0!, { r6-r9 } @
76 b 25f @ copy up done @
77 ldmia r1!, { r6-r10 } @ rw % 16 = 10 or 11
78 subs r2, r2, #10 @
79 stmia r0!, { r6-r10 } @
80 b 25f @ copy up done @
81 ldmia r1!, { r6-r11 } @ rw % 16 = 12 or 13
82 subs r2, r2, #12 @
83 stmia r0!, { r6-r11 } @
84 b 25f @ copy up done @
85 ldmia r1!, { r6-r12 } @ rw % 16 = 14 or 15
86 subs r2, r2, #14 @
87 stmia r0!, { r6-r12 } @
8825: @ copy up done @
89 ble 40f @ finish line @ no 32-byte segments remaining?
9030: @ octword loop @ copy 16 pixels per loop
91 ldmia r1!, { r6-r12, r14 } @
92 subs r2, r2, #16 @
93 stmia r0!, { r6-r12, r14 } @
94 bgt 30b @ octword loop @
9540: @ finish line @
96 ldreqh r6, [r1], #2 @ finish last halfword if eq ...
97 add r1, r1, r4, lsl #1 @
98 streqh r6, [r0], #2 @ ...
99 add r0, r0, r4, lsl #1 @
100 subs r3, r3, #1 @ next line
101 bgt 10b @ copy line @
102 ldmfd sp!, { r4-r12, pc } @ restore regs and return
103 .ltorg @ dump constant pool
104 .size lcd_copy_buffer_rect, .-lcd_copy_buffer_rect
105
106
107/****************************************************************************
108 * void lcd_write_yuv_420_lines(fb_data *dst,
109 * unsigned char const * const src[3],
110 * int width,
111 * int stride);
112 *
113 * |R| |1.000000 -0.000001 1.402000| |Y'|
114 * |G| = |1.000000 -0.334136 -0.714136| |Pb|
115 * |B| |1.000000 1.772000 0.000000| |Pr|
116 * Scaled, normalized, rounded and tweaked to yield RGB 565:
117 * |R| |74 0 101| |Y' - 16| >> 9
118 * |G| = |74 -24 -51| |Cb - 128| >> 8
119 * |B| |74 128 0| |Cr - 128| >> 9
120 *
121 * Write four RGB565 pixels in the following order on each loop:
122 * 1 3 + > down
123 * 2 4 \/ left
124 */
125 .section .icode, "ax", %progbits
126 .align 2
127 .global lcd_write_yuv420_lines
128 .type lcd_write_yuv420_lines, %function
129lcd_write_yuv420_lines:
130 @ r0 = dst
131 @ r1 = yuv_src
132 @ r2 = width
133 @ r3 = stride
134 stmfd sp!, { r4-r12 } @ save non-scratch
135 ldmia r1, { r4, r5, r6 } @ r4 = yuv_src[0] = Y'_p
136 @ r5 = yuv_src[1] = Cb_p
137 @ r6 = yuv_src[2] = Cr_p
138 @ r1 = scratch
139 sub r3, r3, #1 @
14010: @ loop line @
141 ldrb r7, [r4], #1 @ r7 = *Y'_p++;
142 ldrb r8, [r5], #1 @ r8 = *Cb_p++;
143 ldrb r9, [r6], #1 @ r9 = *Cr_p++;
144 @
145 sub r7, r7, #16 @ r7 = Y = (Y' - 16)*74
146 add r12, r7, r7, asl #2 @ actually (Y' - 16)*37 and shift right
147 add r7, r12, r7, asl #5 @ by one less when adding - same for all
148 @
149 sub r8, r8, #128 @ Cb -= 128
150 sub r9, r9, #128 @ Cr -= 128
151 @
152 add r10, r9, r9, asl #1 @ r10 = Cr*51 + Cb*24
153 add r10, r10, r10, asl #4 @
154 add r10, r10, r8, asl #3 @
155 add r10, r10, r8, asl #4 @
156 @
157 add r11, r9, r9, asl #2 @ r9 = Cr*101
158 add r11, r11, r9, asl #5 @
159 add r9, r11, r9, asl #6 @
160 @
161 add r8, r8, #2 @ r8 = bu = (Cb*128 + 128) >> 8
162 mov r8, r8, asr #2 @
163 add r9, r9, #256 @ r9 = rv = (r9 + 256) >> 9
164 mov r9, r9, asr #9 @
165 rsb r10, r10, #128 @ r10 = guv = (-r10 + 128) >> 8
166 mov r10, r10, asr #8 @
167 @ compute R, G, and B
168 add r1, r8, r7, asr #8 @ r1 = b = (Y >> 9) + bu
169 add r11, r9, r7, asr #8 @ r11 = r = (Y >> 9) + rv
170 add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv
171 @
172 orr r12, r1, r11 @ check if clamping is needed...
173 orr r12, r12, r7, asr #1 @ ...at all
174 cmp r12, #31 @
175 bls 15f @ no clamp @
176 cmp r1, #31 @ clamp b
177 mvnhi r1, r1, asr #31 @
178 andhi r1, r1, #31 @
179 cmp r11, #31 @ clamp r
180 mvnhi r11, r11, asr #31 @
181 andhi r11, r11, #31 @
182 cmp r7, #63 @ clamp g
183 mvnhi r7, r7, asr #31 @
184 andhi r7, r7, #63 @
18515: @ no clamp @
186 @
187 ldrb r12, [r4, r3] @ r12 = Y' = *(Y'_p + stride)
188 @
189 orr r1, r1, r7, lsl #5 @ r4 |= (g << 5)
190 orr r1, r1, r11, lsl #11 @ r4 = b | (r << 11)
191 strh r1, [r0], #LCD_WIDTH @ store pixel
192 @
193 sub r7, r12, #16 @ r7 = Y = (Y' - 16)*74
194 add r12, r7, r7, asl #2 @
195 add r7, r12, r7, asl #5 @
196 @ compute R, G, and B
197 add r1, r8, r7, asr #8 @ r1 = b = (Y >> 9) + bu
198 add r11, r9, r7, asr #8 @ r11 = r = (Y >> 9) + rv
199 add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv
200 @
201 orr r12, r1, r11 @ check if clamping is needed...
202 orr r12, r12, r7, asr #1 @ ...at all
203 cmp r12, #31 @
204 bls 15f @ no clamp @
205 cmp r1, #31 @ clamp b
206 mvnhi r1, r1, asr #31 @
207 andhi r1, r1, #31 @
208 cmp r11, #31 @ clamp r
209 mvnhi r11, r11, asr #31 @
210 andhi r11, r11, #31 @
211 cmp r7, #63 @ clamp g
212 mvnhi r7, r7, asr #31 @
213 andhi r7, r7, #63 @
21415: @ no clamp @
215 @
216 ldrb r12, [r4], #1 @ r12 = Y' = *(Y'_p++)
217 @
218 orr r1, r1, r11, lsl #11 @ r1 = b | (r << 11)
219 orr r1, r1, r7, lsl #5 @ r1 |= (g << 5)
220 strh r1, [r0, #-LCD_WIDTH-2] @ store pixel
221 @
222 sub r7, r12, #16 @ r7 = Y = (Y' - 16)*74
223 add r12, r7, r7, asl #2 @
224 add r7, r12, r7, asl #5 @
225 @ compute R, G, and B
226 add r1, r8, r7, asr #8 @ r1 = b = (Y >> 9) + bu
227 add r11, r9, r7, asr #8 @ r11 = r = (Y >> 9) + rv
228 add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv
229 @
230 orr r12, r1, r11 @ check if clamping is needed...
231 orr r12, r12, r7, asr #1 @ ...at all
232 cmp r12, #31 @
233 bls 15f @ no clamp @
234 cmp r1, #31 @ clamp b
235 mvnhi r1, r1, asr #31 @
236 andhi r1, r1, #31 @
237 cmp r11, #31 @ clamp r
238 mvnhi r11, r11, asr #31 @
239 andhi r11, r11, #31 @
240 cmp r7, #63 @ clamp g
241 mvnhi r7, r7, asr #31 @
242 andhi r7, r7, #63 @
24315: @ no clamp @
244 @
245 ldrb r12, [r4, r3] @ r12 = Y' = *(Y'_p + stride)
246 @
247 orr r1, r1, r7, lsl #5 @ r1 = b | (g << 5)
248 orr r1, r1, r11, lsl #11 @ r1 |= (r << 11)
249 strh r1, [r0, #LCD_WIDTH]! @ store pixel
250 @
251 sub r7, r12, #16 @ r7 = Y = (Y' - 16)*74
252 add r12, r7, r7, asl #2 @
253 add r7, r12, r7, asl #5 @
254 @ compute R, G, and B
255 add r1, r8, r7, asr #8 @ r1 = b = (Y >> 9) + bu
256 add r11, r9, r7, asr #8 @ r11 = r = (Y >> 9) + rv
257 add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv
258 @
259 orr r12, r1, r11 @ check if clamping is needed...
260 orr r12, r12, r7, asr #1 @ ...at all
261 cmp r12, #31 @
262 bls 15f @ no clamp @
263 cmp r1, #31 @ clamp b
264 mvnhi r1, r1, asr #31 @
265 andhi r1, r1, #31 @
266 cmp r11, #31 @ clamp r
267 mvnhi r11, r11, asr #31 @
268 andhi r11, r11, #31 @
269 cmp r7, #63 @ clamp g
270 mvnhi r7, r7, asr #31 @
271 andhi r7, r7, #63 @
27215: @ no clamp @
273 @
274 orr r12, r1, r11, lsl #11 @ r12 = b | (r << 11)
275 orr r12, r12, r7, lsl #5 @ r12 |= (g << 5)
276 strh r12, [r0, #-2] @ store pixel
277 add r0, r0, #2*LCD_WIDTH @
278 @
279 subs r2, r2, #2 @ subtract block from width
280 bgt 10b @ loop line @
281 @
282 ldmfd sp!, { r4-r12 } @ restore registers and return
283 bx lr @
284 .ltorg @ dump constant pool
285 .size lcd_write_yuv420_lines, .-lcd_write_yuv420_lines
286
287
288/****************************************************************************
289 * void lcd_write_yuv_420_lines_odither(fb_data *dst,
290 * unsigned char const * const src[3],
291 * int width,
292 * int stride,
293 * int x_screen,
294 * int y_screen);
295 *
296 * |R| |1.000000 -0.000001 1.402000| |Y'|
297 * |G| = |1.000000 -0.334136 -0.714136| |Pb|
298 * |B| |1.000000 1.772000 0.000000| |Pr|
299 * Red scaled at twice g & b but at same precision to place it in correct
300 * bit position after multiply and leave instruction count lower.
301 * |R| |258 0 408| |Y' - 16|
302 * |G| = |149 -49 -104| |Cb - 128|
303 * |B| |149 258 0| |Cr - 128|
304 *
305 * Write four RGB565 pixels in the following order on each loop:
306 * 1 3 + > down
307 * 2 4 \/ left
308 *
309 * Kernel pattern (raw|rotated|use order):
310 * 5 3 4 2 2 6 3 7 row0 row2 > down
311 * 1 7 0 6 | 4 0 5 1 | 2 4 6 0 3 5 7 1 col0 left
312 * 4 2 5 3 | 3 7 2 6 | 3 5 7 1 2 4 6 0 col2 \/
313 * 0 6 1 7 5 1 4 0
314 */
315 .section .icode, "ax", %progbits
316 .align 2
317 .global lcd_write_yuv420_lines_odither
318 .type lcd_write_yuv420_lines_odither, %function
319lcd_write_yuv420_lines_odither:
320 @ r0 = dst
321 @ r1 = yuv_src
322 @ r2 = width
323 @ r3 = stride
324 @ [sp] = x_screen
325 @ [sp+4] = y_screen
326 stmfd sp!, { r4-r12, lr } @ save non-scratch
327 ldmia r1, { r4, r5, r6 } @ r4 = yuv_src[0] = Y'_p
328 @ r5 = yuv_src[1] = Cb_p
329 @ r6 = yuv_src[2] = Cr_p
330 @
331 sub r3, r3, #1 @
332 add r1, sp, #40 @ Line up pattern and kernel quadrant
333 ldmia r1, { r12, r14 } @
334 eor r14, r14, r12 @
335 and r14, r14, #0x2 @
336 mov r14, r14, lsl #6 @ 0x00 or 0x80
33710: @ loop line @
338 @
339 ldrb r7, [r4], #1 @ r7 = *Y'_p++;
340 ldrb r8, [r5], #1 @ r8 = *Cb_p++;
341 ldrb r9, [r6], #1 @ r9 = *Cr_p++;
342 @
343 eor r14, r14, #0x80 @ flip pattern quadrant
344 @
345 sub r7, r7, #16 @ r7 = Y = (Y' - 16)*149
346 add r12, r7, r7, asl #2 @
347 add r12, r12, r12, asl #4 @
348 add r7, r12, r7, asl #6 @
349 @
350 sub r8, r8, #128 @ Cb -= 128
351 sub r9, r9, #128 @ Cr -= 128
352 @
353 add r10, r8, r8, asl #4 @ r10 = guv = Cr*104 + Cb*49
354 add r10, r10, r8, asl #5 @
355 add r10, r10, r9, asl #3 @
356 add r10, r10, r9, asl #5 @
357 add r10, r10, r9, asl #6 @
358 @
359 mov r8, r8, asl #1 @ r8 = bu = Cb*258
360 add r8, r8, r8, asl #7 @
361 @
362 add r9, r9, r9, asl #1 @ r9 = rv = Cr*408
363 add r9, r9, r9, asl #4 @
364 mov r9, r9, asl #3 @
365 @
366 @ compute R, G, and B
367 add r1, r8, r7 @ r1 = b' = Y + bu
368 add r11, r9, r7, asl #1 @ r11 = r' = Y*2 + rv
369 rsb r7, r10, r7 @ r7 = g' = Y + guv
370 @
371 @ r8 = bu, r9 = rv, r10 = guv
372 @
373 sub r12, r1, r1, lsr #5 @ r1 = 31/32*b + b/256
374 add r1, r12, r1, lsr #8 @
375 @
376 sub r12, r11, r11, lsr #5 @ r11 = 31/32*r + r/256
377 add r11, r12, r11, lsr #8 @
378 @
379 sub r12, r7, r7, lsr #6 @ r7 = 63/64*g + g/256
380 add r7, r12, r7, lsr #8 @
381 @
382 add r12, r14, #0x100 @
383 @
384 add r1, r1, r12 @ b = r1 + delta
385 add r11, r11, r12, lsl #1 @ r = r11 + delta*2
386 add r7, r7, r12, lsr #1 @ g = r7 + delta/2
387 @
388 orr r12, r1, r11, asr #1 @ check if clamping is needed...
389 orr r12, r12, r7 @ ...at all
390 movs r12, r12, asr #15 @
391 beq 15f @ no clamp @
392 movs r12, r1, asr #15 @ clamp b
393 mvnne r1, r12, lsr #15 @
394 andne r1, r1, #0x7c00 @ mask b only if clamped
395 movs r12, r11, asr #16 @ clamp r
396 mvnne r11, r12, lsr #16 @
397 movs r12, r7, asr #15 @ clamp g
398 mvnne r7, r12, lsr #15 @
39915: @ no clamp @
400 @
401 ldrb r12, [r4, r3] @ r12 = Y' = *(Y'_p + stride)
402 @
403 and r11, r11, #0xf800 @ pack pixel
404 and r7, r7, #0x7e00 @ r1 = pixel = (r & 0xf800) |
405 orr r11, r11, r7, lsr #4 @ ((g & 0x7e00) >> 4) |
406 orr r1, r11, r1, lsr #10 @ (b >> 10)
407 @
408 strh r1, [r0], #LCD_WIDTH @ store pixel
409 @
410 sub r7, r12, #16 @ r7 = Y = (Y' - 16)*149
411 add r12, r7, r7, asl #2 @
412 add r12, r12, r12, asl #4 @
413 add r7, r12, r7, asl #6 @
414 @ compute R, G, and B
415 add r1, r8, r7 @ r1 = b' = Y + bu
416 add r11, r9, r7, asl #1 @ r11 = r' = Y*2 + rv
417 rsb r7, r10, r7 @ r7 = g' = Y + guv
418 @
419 sub r12, r1, r1, lsr #5 @ r1 = 31/32*b' + b'/256
420 add r1, r12, r1, lsr #8 @
421 @
422 sub r12, r11, r11, lsr #5 @ r11 = 31/32*r' + r'/256
423 add r11, r12, r11, lsr #8 @
424 @
425 sub r12, r7, r7, lsr #6 @ r7 = 63/64*g' + g'/256
426 add r7, r12, r7, lsr #8 @
427 @
428 add r12, r14, #0x200 @
429 @
430 add r1, r1, r12 @ b = r1 + delta
431 add r11, r11, r12, lsl #1 @ r = r11 + delta*2
432 add r7, r7, r12, lsr #1 @ g = r7 + delta/2
433 @
434 orr r12, r1, r11, asr #1 @ check if clamping is needed...
435 orr r12, r12, r7 @ ...at all
436 movs r12, r12, asr #15 @
437 beq 15f @ no clamp @
438 movs r12, r1, asr #15 @ clamp b
439 mvnne r1, r12, lsr #15 @
440 andne r1, r1, #0x7c00 @ mask b only if clamped
441 movs r12, r11, asr #16 @ clamp r
442 mvnne r11, r12, lsr #16 @
443 movs r12, r7, asr #15 @ clamp g
444 mvnne r7, r12, lsr #15 @
44515: @ no clamp @
446 @
447 ldrb r12, [r4], #1 @ r12 = Y' = *(Y'_p++)
448 @
449 and r11, r11, #0xf800 @ pack pixel
450 and r7, r7, #0x7e00 @ r1 = pixel = (r & 0xf800) |
451 orr r11, r11, r7, lsr #4 @ ((g & 0x7e00) >> 4) |
452 orr r1, r11, r1, lsr #10 @ (b >> 10)
453 @
454 strh r1, [r0, #-LCD_WIDTH-2] @ store pixel
455 @
456 sub r7, r12, #16 @ r7 = Y = (Y' - 16)*149
457 add r12, r7, r7, asl #2 @
458 add r12, r12, r12, asl #4 @
459 add r7, r12, r7, asl #6 @
460 @ compute R, G, and B
461 add r1, r8, r7 @ r1 = b' = Y + bu
462 add r11, r9, r7, asl #1 @ r11 = r' = Y*2 + rv
463 rsb r7, r10, r7 @ r7 = g' = Y + guv
464 @
465 @ r8 = bu, r9 = rv, r10 = guv
466 @
467 sub r12, r1, r1, lsr #5 @ r1 = 31/32*b' + b'/256
468 add r1, r12, r1, lsr #8 @
469 @
470 sub r12, r11, r11, lsr #5 @ r11 = 31/32*r' + r'/256
471 add r11, r12, r11, lsr #8 @
472 @
473 sub r12, r7, r7, lsr #6 @ r7 = 63/64*g' + g'/256
474 add r7, r12, r7, lsr #8 @
475 @
476 add r12, r14, #0x300 @
477 @
478 add r1, r1, r12 @ b = r1 + delta
479 add r11, r11, r12, lsl #1 @ r = r11 + delta*2
480 add r7, r7, r12, lsr #1 @ g = r7 + delta/2
481 @
482 orr r12, r1, r11, asr #1 @ check if clamping is needed...
483 orr r12, r12, r7 @ ...at all
484 movs r12, r12, asr #15 @
485 beq 15f @ no clamp @
486 movs r12, r1, asr #15 @ clamp b
487 mvnne r1, r12, lsr #15 @
488 andne r1, r1, #0x7c00 @ mask b only if clamped
489 movs r12, r11, asr #16 @ clamp r
490 mvnne r11, r12, lsr #16 @
491 movs r12, r7, asr #15 @ clamp g
492 mvnne r7, r12, lsr #15 @
49315: @ no clamp @
494 @
495 ldrb r12, [r4, r3] @ r12 = Y' = *(Y'_p + stride)
496 @
497 and r11, r11, #0xf800 @ pack pixel
498 and r7, r7, #0x7e00 @ r1 = pixel = (r & 0xf800) |
499 orr r11, r11, r7, lsr #4 @ ((g & 0x7e00) >> 4) |
500 orr r1, r11, r1, lsr #10 @ (b >> 10)
501 @
502 strh r1, [r0, #LCD_WIDTH]! @ store pixel
503 @
504 sub r7, r12, #16 @ r7 = Y = (Y' - 16)*149
505 add r12, r7, r7, asl #2 @
506 add r12, r12, r12, asl #4 @
507 add r7, r12, r7, asl #6 @
508 @ compute R, G, and B
509 add r1, r8, r7 @ r1 = b' = Y + bu
510 add r11, r9, r7, asl #1 @ r11 = r' = Y*2 + rv
511 rsb r7, r10, r7 @ r7 = g' = Y + guv
512 @
513 sub r12, r1, r1, lsr #5 @ r1 = 31/32*b + b/256
514 add r1, r12, r1, lsr #8 @
515 @
516 sub r12, r11, r11, lsr #5 @ r11 = 31/32*r + r/256
517 add r11, r12, r11, lsr #8 @
518 @
519 sub r12, r7, r7, lsr #6 @ r7 = 63/64*g + g/256
520 add r7, r12, r7, lsr #8 @
521 @
522 @ This element is zero - use r14 @
523 @
524 add r1, r1, r14 @ b = r1 + delta
525 add r11, r11, r14, lsl #1 @ r = r11 + delta*2
526 add r7, r7, r14, lsr #1 @ g = r7 + delta/2
527 @
528 orr r12, r1, r11, asr #1 @ check if clamping is needed...
529 orr r12, r12, r7 @ ...at all
530 movs r12, r12, asr #15 @
531 beq 15f @ no clamp @
532 movs r12, r1, asr #15 @ clamp b
533 mvnne r1, r12, lsr #15 @
534 andne r1, r1, #0x7c00 @ mask b only if clamped
535 movs r12, r11, asr #16 @ clamp r
536 mvnne r11, r12, lsr #16 @
537 movs r12, r7, asr #15 @ clamp g
538 mvnne r7, r12, lsr #15 @
53915: @ no clamp @
540 @
541 and r11, r11, #0xf800 @ pack pixel
542 and r7, r7, #0x7e00 @ r1 = pixel = (r & 0xf800) |
543 orr r11, r11, r7, lsr #4 @ ((g & 0x7e00) >> 4) |
544 orr r1, r11, r1, lsr #10 @ (b >> 10)
545 @
546 strh r1, [r0, #-2] @ store pixel
547 add r0, r0, #2*LCD_WIDTH @
548 @
549 subs r2, r2, #2 @ subtract block from width
550 bgt 10b @ loop line @
551 @
552 ldmfd sp!, { r4-r12, pc } @ restore registers and return
553 .ltorg @ dump constant pool
554 .size lcd_write_yuv420_lines_odither, .-lcd_write_yuv420_lines_odither
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
deleted file mode 100644
index 4926c7fa79..0000000000
--- a/firmware/target/arm/s3c2440/gigabeat-fx/lcd-as-meg-fx.S
+++ /dev/null
@@ -1,279 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 by Michael Sevakis
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include "config.h"
21#include "cpu.h"
22
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/****************************************************************************
105 * void lcd_write_yuv_420_lines(fb_data *dst,
106 * unsigned char const * const src[3],
107 * int width,
108 * int stride);
109 *
110 * |R| |1.000000 -0.000001 1.402000| |Y'|
111 * |G| = |1.000000 -0.334136 -0.714136| |Pb|
112 * |B| |1.000000 1.772000 0.000000| |Pr|
113 * Scaled, normalized, rounded and tweaked to yield RGB 565:
114 * |R| |74 0 101| |Y' - 16| >> 9
115 * |G| = |74 -24 -51| |Cb - 128| >> 8
116 * |B| |74 128 0| |Cr - 128| >> 9
117 *
118 * Write four RGB565 pixels in the following order on each loop:
119 * 1 3 + > down
120 * 2 4 \/ left
121 */
122 .section .icode, "ax", %progbits
123 .align 2
124 .global lcd_write_yuv420_lines
125 .type lcd_write_yuv420_lines, %function
126lcd_write_yuv420_lines:
127 @ r0 = dst
128 @ r1 = yuv_src
129 @ r2 = width
130 @ r3 = stride
131 stmfd sp!, { r4-r12 } @ save non-scratch
132 ldmia r1, { r4, r5, r6 } @ r4 = yuv_src[0] = Y'_p
133 @ r5 = yuv_src[1] = Cb_p
134 @ r6 = yuv_src[2] = Cr_p
135 @ r1 = scratch
13610: @ loop line @
137 ldrb r7, [r4] @ r7 = *Y'_p;
138 ldrb r8, [r5], #1 @ r8 = *Cb_p++;
139 ldrb r9, [r6], #1 @ r9 = *Cr_p++;
140 @
141 sub r7, r7, #16 @ r7 = Y = (Y' - 16)*74
142 add r12, r7, r7, asl #2 @ actually (Y' - 16)*37 and shift right
143 add r7, r12, r7, asl #5 @ by one less when adding - same for all
144 @
145 sub r8, r8, #128 @ Cb -= 128
146 sub r9, r9, #128 @ Cr -= 128
147 @
148 add r10, r9, r9, asl #1 @ r10 = Cr*51 + Cb*24
149 add r10, r10, r10, asl #4 @
150 add r10, r10, r8, asl #3 @
151 add r10, r10, r8, asl #4 @
152 @
153 add r11, r9, r9, asl #2 @ r9 = Cr*101
154 add r11, r11, r9, asl #5 @
155 add r9, r11, r9, asl #6 @
156 @
157 add r8, r8, #2 @ r8 = bu = (Cb*128 + 128) >> 8
158 mov r8, r8, asr #2 @
159 add r9, r9, #256 @ r9 = rv = (r9 + 256) >> 9
160 mov r9, r9, asr #9 @
161 rsb r10, r10, #128 @ r10 = guv = (-r10 + 128) >> 8
162 mov r10, r10, asr #8 @
163 @ compute R, G, and B
164 add r1, r8, r7, asr #8 @ r1 = b = (Y >> 9) + bu
165 add r11, r9, r7, asr #8 @ r11 = r = (Y >> 9) + rv
166 add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv
167 @
168 orr r12, r1, r11 @ check if clamping is needed...
169 orr r12, r12, r7, asr #1 @ ...at all
170 cmp r12, #31 @
171 bls 15f @ no clamp @
172 cmp r1, #31 @ clamp b
173 mvnhi r1, r1, asr #31 @
174 andhi r1, r1, #31 @
175 cmp r11, #31 @ clamp r
176 mvnhi r11, r11, asr #31 @
177 andhi r11, r11, #31 @
178 cmp r7, #63 @ clamp g
179 mvnhi r7, r7, asr #31 @
180 andhi r7, r7, #63 @
18115: @ no clamp @
182 @
183 orr r12, r1, r7, lsl #5 @ r4 |= (g << 5)
184 ldrb r7, [r4, r3] @ r7 = Y' = *(Y'_p + stride)
185 orr r12, r12, r11, lsl #11 @ r4 = b | (r << 11)
186 strh r12, [r0] @ store pixel
187 @
188 sub r7, r7, #16 @ r7 = Y = (Y' - 16)*74
189 add r12, r7, r7, asl #2 @
190 add r7, r12, r7, asl #5 @
191 @ compute R, G, and B
192 add r1, r8, r7, asr #8 @ r1 = b = (Y >> 9) + bu
193 add r11, r9, r7, asr #8 @ r11 = r = (Y >> 9) + rv
194 add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv
195 @
196 orr r12, r1, r11 @ check if clamping is needed...
197 orr r12, r12, r7, asr #1 @ ...at all
198 cmp r12, #31 @
199 bls 15f @ no clamp @
200 cmp r1, #31 @ clamp b
201 mvnhi r1, r1, asr #31 @
202 andhi r1, r1, #31 @
203 cmp r11, #31 @ clamp r
204 mvnhi r11, r11, asr #31 @
205 andhi r11, r11, #31 @
206 cmp r7, #63 @ clamp g
207 mvnhi r7, r7, asr #31 @
208 andhi r7, r7, #63 @
20915: @ no clamp @
210 @
211 orr r12, r1, r11, lsl #11 @ r12 = b | (r << 11)
212 orr r12, r12, r7, lsl #5 @ r12 |= (g << 5)
213 ldrb r7, [r4, #1]! @ r7 = Y' = *(++Y'_p)
214 strh r12, [r0, #-2] @ store pixel
215 add r0, r0, #2*LCD_WIDTH @
216 @
217 sub r7, r7, #16 @ r7 = Y = (Y' - 16)*74
218 add r12, r7, r7, asl #2 @
219 add r7, r12, r7, asl #5 @
220 @ compute R, G, and B
221 add r1, r8, r7, asr #8 @ r1 = b = (Y >> 9) + bu
222 add r11, r9, r7, asr #8 @ r11 = r = (Y >> 9) + rv
223 add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv
224 @
225 orr r12, r1, r11 @ check if clamping is needed...
226 orr r12, r12, r7, asr #1 @ ...at all
227 cmp r12, #31 @
228 bls 15f @ no clamp @
229 cmp r1, #31 @ clamp b
230 mvnhi r1, r1, asr #31 @
231 andhi r1, r1, #31 @
232 cmp r11, #31 @ clamp r
233 mvnhi r11, r11, asr #31 @
234 andhi r11, r11, #31 @
235 cmp r7, #63 @ clamp g
236 mvnhi r7, r7, asr #31 @
237 andhi r7, r7, #63 @
23815: @ no clamp @
239 @
240 orr r12, r1, r7, lsl #5 @ r12 = b | (g << 5)
241 ldrb r7, [r4, r3] @ r7 = Y' = *(Y'_p + stride)
242 orr r12, r12, r11, lsl #11 @ r12 |= (r << 11)
243 strh r12, [r0] @ store pixel
244 @
245 sub r7, r7, #16 @ r7 = Y = (Y' - 16)*74
246 add r12, r7, r7, asl #2 @
247 add r7, r12, r7, asl #5 @
248 @ compute R, G, and B
249 add r1, r8, r7, asr #8 @ r1 = b = (Y >> 9) + bu
250 add r11, r9, r7, asr #8 @ r11 = r = (Y >> 9) + rv
251 add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv
252 @
253 orr r12, r1, r11 @ check if clamping is needed...
254 orr r12, r12, r7, asr #1 @ ...at all
255 cmp r12, #31 @
256 bls 15f @ no clamp @
257 cmp r1, #31 @ clamp b
258 mvnhi r1, r1, asr #31 @
259 andhi r1, r1, #31 @
260 cmp r11, #31 @ clamp r
261 mvnhi r11, r11, asr #31 @
262 andhi r11, r11, #31 @
263 cmp r7, #63 @ clamp g
264 mvnhi r7, r7, asr #31 @
265 andhi r7, r7, #63 @
26615: @ no clamp @
267 @
268 orr r12, r1, r11, lsl #11 @ r12 = b | (r << 11)
269 orr r12, r12, r7, lsl #5 @ r12 |= (g << 5)
270 strh r12, [r0, #-2] @ store pixel
271 add r0, r0, #2*LCD_WIDTH @
272 add r4, r4, #1 @
273 @
274 subs r2, r2, #2 @ subtract block from width
275 bgt 10b @ loop line @
276 @
277 ldmfd sp!, { r4-r12 } @ restore registers and return
278 bx lr @
279 .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 ab7c91437c..91b2eae986 100644
--- a/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c
@@ -9,6 +9,7 @@
9 9
10static volatile bool lcd_on = true; 10static volatile bool lcd_on = true;
11volatile bool lcd_poweroff = false; 11volatile bool lcd_poweroff = false;
12static unsigned lcd_yuv_options = 0;
12/* 13/*
13** These are imported from lcd-16bit.c 14** These are imported from lcd-16bit.c
14*/ 15*/
@@ -248,11 +249,22 @@ void lcd_bitmap_transparent_part(const fb_data *src, int src_x, int src_y,
248 ); 249 );
249} 250}
250 251
252void lcd_yuv_set_options(unsigned options)
253{
254 lcd_yuv_options = options;
255}
256
251/* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */ 257/* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */
252extern void lcd_write_yuv420_lines(fb_data *dst, 258extern void lcd_write_yuv420_lines(fb_data *dst,
253 unsigned char const * const src[3], 259 unsigned char const * const src[3],
254 int width, 260 int width,
255 int stride); 261 int stride);
262extern void lcd_write_yuv420_lines_odither(fb_data *dst,
263 unsigned char const * const src[3],
264 int width,
265 int stride,
266 int x_screen, /* To align dither pattern */
267 int y_screen);
256/* Performance function to blit a YUV bitmap directly to the LCD */ 268/* Performance function to blit a YUV bitmap directly to the LCD */
257/* For the Gigabeat - show it rotated */ 269/* For the Gigabeat - show it rotated */
258/* So the LCD_WIDTH is now the height */ 270/* So the LCD_WIDTH is now the height */
@@ -272,22 +284,39 @@ void lcd_yuv_blit(unsigned char * const src[3],
272 width &= ~1; 284 width &= ~1;
273 height >>= 1; 285 height >>= 1;
274 286
275 fb_data *dst = (fb_data*)FRAME + x * LCD_WIDTH + (LCD_WIDTH - y) - 1; 287 y = LCD_WIDTH - 1 - y;
288 fb_data *dst = (fb_data*)FRAME + x * LCD_WIDTH + y;
276 289
277 z = stride*src_y; 290 z = stride*src_y;
278 yuv_src[0] = src[0] + z + src_x; 291 yuv_src[0] = src[0] + z + src_x;
279 yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1); 292 yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1);
280 yuv_src[2] = src[2] + (yuv_src[1] - src[1]); 293 yuv_src[2] = src[2] + (yuv_src[1] - src[1]);
281 294
282 do 295 if (lcd_yuv_options & LCD_YUV_DITHER)
296 {
297 do
298 {
299 lcd_write_yuv420_lines_odither(dst, yuv_src, width, stride, y, x);
300 yuv_src[0] += stride << 1; /* Skip down two luma lines */
301 yuv_src[1] += stride >> 1; /* Skip down one chroma line */
302 yuv_src[2] += stride >> 1;
303 dst -= 2;
304 y -= 2;
305 }
306 while (--height > 0);
307 }
308 else
283 { 309 {
284 lcd_write_yuv420_lines(dst, yuv_src, width, stride); 310 do
285 yuv_src[0] += stride << 1; /* Skip down two luma lines */ 311 {
286 yuv_src[1] += stride >> 1; /* Skip down one chroma line */ 312 lcd_write_yuv420_lines(dst, yuv_src, width, stride);
287 yuv_src[2] += stride >> 1; 313 yuv_src[0] += stride << 1; /* Skip down two luma lines */
288 dst -= 2; 314 yuv_src[1] += stride >> 1; /* Skip down one chroma line */
315 yuv_src[2] += stride >> 1;
316 dst -= 2;
317 }
318 while (--height > 0);
289 } 319 }
290 while (--height > 0);
291} 320}
292 321
293void lcd_set_contrast(int val) { 322void lcd_set_contrast(int val) {
diff --git a/firmware/target/arm/sandisk/sansa-e200/lcd-as-e200.S b/firmware/target/arm/sandisk/sansa-e200/lcd-as-e200.S
deleted file mode 100644
index 4926c7fa79..0000000000
--- a/firmware/target/arm/sandisk/sansa-e200/lcd-as-e200.S
+++ /dev/null
@@ -1,279 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 by Michael Sevakis
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include "config.h"
21#include "cpu.h"
22
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/****************************************************************************
105 * void lcd_write_yuv_420_lines(fb_data *dst,
106 * unsigned char const * const src[3],
107 * int width,
108 * int stride);
109 *
110 * |R| |1.000000 -0.000001 1.402000| |Y'|
111 * |G| = |1.000000 -0.334136 -0.714136| |Pb|
112 * |B| |1.000000 1.772000 0.000000| |Pr|
113 * Scaled, normalized, rounded and tweaked to yield RGB 565:
114 * |R| |74 0 101| |Y' - 16| >> 9
115 * |G| = |74 -24 -51| |Cb - 128| >> 8
116 * |B| |74 128 0| |Cr - 128| >> 9
117 *
118 * Write four RGB565 pixels in the following order on each loop:
119 * 1 3 + > down
120 * 2 4 \/ left
121 */
122 .section .icode, "ax", %progbits
123 .align 2
124 .global lcd_write_yuv420_lines
125 .type lcd_write_yuv420_lines, %function
126lcd_write_yuv420_lines:
127 @ r0 = dst
128 @ r1 = yuv_src
129 @ r2 = width
130 @ r3 = stride
131 stmfd sp!, { r4-r12 } @ save non-scratch
132 ldmia r1, { r4, r5, r6 } @ r4 = yuv_src[0] = Y'_p
133 @ r5 = yuv_src[1] = Cb_p
134 @ r6 = yuv_src[2] = Cr_p
135 @ r1 = scratch
13610: @ loop line @
137 ldrb r7, [r4] @ r7 = *Y'_p;
138 ldrb r8, [r5], #1 @ r8 = *Cb_p++;
139 ldrb r9, [r6], #1 @ r9 = *Cr_p++;
140 @
141 sub r7, r7, #16 @ r7 = Y = (Y' - 16)*74
142 add r12, r7, r7, asl #2 @ actually (Y' - 16)*37 and shift right
143 add r7, r12, r7, asl #5 @ by one less when adding - same for all
144 @
145 sub r8, r8, #128 @ Cb -= 128
146 sub r9, r9, #128 @ Cr -= 128
147 @
148 add r10, r9, r9, asl #1 @ r10 = Cr*51 + Cb*24
149 add r10, r10, r10, asl #4 @
150 add r10, r10, r8, asl #3 @
151 add r10, r10, r8, asl #4 @
152 @
153 add r11, r9, r9, asl #2 @ r9 = Cr*101
154 add r11, r11, r9, asl #5 @
155 add r9, r11, r9, asl #6 @
156 @
157 add r8, r8, #2 @ r8 = bu = (Cb*128 + 128) >> 8
158 mov r8, r8, asr #2 @
159 add r9, r9, #256 @ r9 = rv = (r9 + 256) >> 9
160 mov r9, r9, asr #9 @
161 rsb r10, r10, #128 @ r10 = guv = (-r10 + 128) >> 8
162 mov r10, r10, asr #8 @
163 @ compute R, G, and B
164 add r1, r8, r7, asr #8 @ r1 = b = (Y >> 9) + bu
165 add r11, r9, r7, asr #8 @ r11 = r = (Y >> 9) + rv
166 add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv
167 @
168 orr r12, r1, r11 @ check if clamping is needed...
169 orr r12, r12, r7, asr #1 @ ...at all
170 cmp r12, #31 @
171 bls 15f @ no clamp @
172 cmp r1, #31 @ clamp b
173 mvnhi r1, r1, asr #31 @
174 andhi r1, r1, #31 @
175 cmp r11, #31 @ clamp r
176 mvnhi r11, r11, asr #31 @
177 andhi r11, r11, #31 @
178 cmp r7, #63 @ clamp g
179 mvnhi r7, r7, asr #31 @
180 andhi r7, r7, #63 @
18115: @ no clamp @
182 @
183 orr r12, r1, r7, lsl #5 @ r4 |= (g << 5)
184 ldrb r7, [r4, r3] @ r7 = Y' = *(Y'_p + stride)
185 orr r12, r12, r11, lsl #11 @ r4 = b | (r << 11)
186 strh r12, [r0] @ store pixel
187 @
188 sub r7, r7, #16 @ r7 = Y = (Y' - 16)*74
189 add r12, r7, r7, asl #2 @
190 add r7, r12, r7, asl #5 @
191 @ compute R, G, and B
192 add r1, r8, r7, asr #8 @ r1 = b = (Y >> 9) + bu
193 add r11, r9, r7, asr #8 @ r11 = r = (Y >> 9) + rv
194 add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv
195 @
196 orr r12, r1, r11 @ check if clamping is needed...
197 orr r12, r12, r7, asr #1 @ ...at all
198 cmp r12, #31 @
199 bls 15f @ no clamp @
200 cmp r1, #31 @ clamp b
201 mvnhi r1, r1, asr #31 @
202 andhi r1, r1, #31 @
203 cmp r11, #31 @ clamp r
204 mvnhi r11, r11, asr #31 @
205 andhi r11, r11, #31 @
206 cmp r7, #63 @ clamp g
207 mvnhi r7, r7, asr #31 @
208 andhi r7, r7, #63 @
20915: @ no clamp @
210 @
211 orr r12, r1, r11, lsl #11 @ r12 = b | (r << 11)
212 orr r12, r12, r7, lsl #5 @ r12 |= (g << 5)
213 ldrb r7, [r4, #1]! @ r7 = Y' = *(++Y'_p)
214 strh r12, [r0, #-2] @ store pixel
215 add r0, r0, #2*LCD_WIDTH @
216 @
217 sub r7, r7, #16 @ r7 = Y = (Y' - 16)*74
218 add r12, r7, r7, asl #2 @
219 add r7, r12, r7, asl #5 @
220 @ compute R, G, and B
221 add r1, r8, r7, asr #8 @ r1 = b = (Y >> 9) + bu
222 add r11, r9, r7, asr #8 @ r11 = r = (Y >> 9) + rv
223 add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv
224 @
225 orr r12, r1, r11 @ check if clamping is needed...
226 orr r12, r12, r7, asr #1 @ ...at all
227 cmp r12, #31 @
228 bls 15f @ no clamp @
229 cmp r1, #31 @ clamp b
230 mvnhi r1, r1, asr #31 @
231 andhi r1, r1, #31 @
232 cmp r11, #31 @ clamp r
233 mvnhi r11, r11, asr #31 @
234 andhi r11, r11, #31 @
235 cmp r7, #63 @ clamp g
236 mvnhi r7, r7, asr #31 @
237 andhi r7, r7, #63 @
23815: @ no clamp @
239 @
240 orr r12, r1, r7, lsl #5 @ r12 = b | (g << 5)
241 ldrb r7, [r4, r3] @ r7 = Y' = *(Y'_p + stride)
242 orr r12, r12, r11, lsl #11 @ r12 |= (r << 11)
243 strh r12, [r0] @ store pixel
244 @
245 sub r7, r7, #16 @ r7 = Y = (Y' - 16)*74
246 add r12, r7, r7, asl #2 @
247 add r7, r12, r7, asl #5 @
248 @ compute R, G, and B
249 add r1, r8, r7, asr #8 @ r1 = b = (Y >> 9) + bu
250 add r11, r9, r7, asr #8 @ r11 = r = (Y >> 9) + rv
251 add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv
252 @
253 orr r12, r1, r11 @ check if clamping is needed...
254 orr r12, r12, r7, asr #1 @ ...at all
255 cmp r12, #31 @
256 bls 15f @ no clamp @
257 cmp r1, #31 @ clamp b
258 mvnhi r1, r1, asr #31 @
259 andhi r1, r1, #31 @
260 cmp r11, #31 @ clamp r
261 mvnhi r11, r11, asr #31 @
262 andhi r11, r11, #31 @
263 cmp r7, #63 @ clamp g
264 mvnhi r7, r7, asr #31 @
265 andhi r7, r7, #63 @
26615: @ no clamp @
267 @
268 orr r12, r1, r11, lsl #11 @ r12 = b | (r << 11)
269 orr r12, r12, r7, lsl #5 @ r12 |= (g << 5)
270 strh r12, [r0, #-2] @ store pixel
271 add r0, r0, #2*LCD_WIDTH @
272 add r4, r4, #1 @
273 @
274 subs r2, r2, #2 @ subtract block from width
275 bgt 10b @ loop line @
276 @
277 ldmfd sp!, { r4-r12 } @ restore registers and return
278 bx lr @
279 .size lcd_write_yuv420_lines, .-lcd_write_yuv420_lines
diff --git a/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c b/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c
index 3e1f74d7a1..0d3a1a3049 100644
--- a/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c
+++ b/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c
@@ -29,6 +29,7 @@
29/* Power and display status */ 29/* Power and display status */
30static bool power_on = false; /* Is the power turned on? */ 30static bool power_on = false; /* Is the power turned on? */
31static bool display_on NOCACHEBSS_ATTR = false; /* Is the display turned on? */ 31static bool display_on NOCACHEBSS_ATTR = false; /* Is the display turned on? */
32static unsigned lcd_yuv_options NOCACHEBSS_ATTR = 0;
32 33
33/* Reverse Flag */ 34/* Reverse Flag */
34#define R_DISP_CONTROL_NORMAL 0x0004 35#define R_DISP_CONTROL_NORMAL 0x0004
@@ -625,11 +626,22 @@ void lcd_blit(const fb_data* data, int x, int by, int width,
625 (void)stride; 626 (void)stride;
626} 627}
627 628
629void lcd_yuv_set_options(unsigned options)
630{
631 lcd_yuv_options = options;
632}
633
628/* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */ 634/* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */
629extern void lcd_write_yuv420_lines(fb_data *dst, 635extern void lcd_write_yuv420_lines(fb_data *dst,
630 unsigned char const * const src[3], 636 unsigned char const * const src[3],
631 int width, 637 int width,
632 int stride); 638 int stride);
639extern void lcd_write_yuv420_lines_odither(fb_data *dst,
640 unsigned char const * const src[3],
641 int width,
642 int stride,
643 int x_screen, /* To align dither pattern */
644 int y_screen);
633/* Performance function to blit a YUV bitmap directly to the LCD */ 645/* Performance function to blit a YUV bitmap directly to the LCD */
634/* For the e200 - show it rotated */ 646/* For the e200 - show it rotated */
635/* So the LCD_WIDTH is now the height */ 647/* So the LCD_WIDTH is now the height */
@@ -647,21 +659,38 @@ void lcd_yuv_blit(unsigned char * const src[3],
647 width &= ~1; 659 width &= ~1;
648 height >>= 1; 660 height >>= 1;
649 661
662 y = LCD_WIDTH - 1 - y;
650 fb_data *dst = (fb_data*)lcd_driver_framebuffer + 663 fb_data *dst = (fb_data*)lcd_driver_framebuffer +
651 x * LCD_WIDTH + (LCD_WIDTH - y) - 1; 664 x * LCD_WIDTH + y;
652 665
653 z = stride*src_y; 666 z = stride*src_y;
654 yuv_src[0] = src[0] + z + src_x; 667 yuv_src[0] = src[0] + z + src_x;
655 yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1); 668 yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1);
656 yuv_src[2] = src[2] + (yuv_src[1] - src[1]); 669 yuv_src[2] = src[2] + (yuv_src[1] - src[1]);
657 670
658 do 671 if (lcd_yuv_options & LCD_YUV_DITHER)
672 {
673 do
674 {
675 lcd_write_yuv420_lines_odither(dst, yuv_src, width, stride, y, x);
676 yuv_src[0] += stride << 1; /* Skip down two luma lines */
677 yuv_src[1] += stride >> 1; /* Skip down one chroma line */
678 yuv_src[2] += stride >> 1;
679 dst -= 2;
680 y -= 2;
681 }
682 while (--height > 0);
683 }
684 else
659 { 685 {
660 lcd_write_yuv420_lines(dst, yuv_src, width, stride); 686 do
661 yuv_src[0] += stride << 1; /* Skip down two luma lines */ 687 {
662 yuv_src[1] += stride >> 1; /* Skip down one chroma line */ 688 lcd_write_yuv420_lines(dst, yuv_src, width, stride);
663 yuv_src[2] += stride >> 1; 689 yuv_src[0] += stride << 1; /* Skip down two luma lines */
664 dst -= 2; 690 yuv_src[1] += stride >> 1; /* Skip down one chroma line */
691 yuv_src[2] += stride >> 1;
692 dst -= 2;
693 }
694 while (--height > 0);
665 } 695 }
666 while (--height > 0);
667} 696}
diff --git a/uisimulator/sdl/lcd-bitmap.c b/uisimulator/sdl/lcd-bitmap.c
index da6acce1bc..12cc063288 100644
--- a/uisimulator/sdl/lcd-bitmap.c
+++ b/uisimulator/sdl/lcd-bitmap.c
@@ -159,3 +159,207 @@ void sim_lcd_ex_update_rect(int x_start, int y_start, int width, int height)
159} 159}
160#endif 160#endif
161 161
162#ifdef HAVE_LCD_COLOR
163/**
164 * |R| |1.000000 -0.000001 1.402000| |Y'|
165 * |G| = |1.000000 -0.334136 -0.714136| |Pb|
166 * |B| |1.000000 1.772000 0.000000| |Pr|
167 * Scaled, normalized, rounded and tweaked to yield RGB 565:
168 * |R| |74 0 101| |Y' - 16| >> 9
169 * |G| = |74 -24 -51| |Cb - 128| >> 8
170 * |B| |74 128 0| |Cr - 128| >> 9
171 */
172#define YFAC (74)
173#define RVFAC (101)
174#define GUFAC (-24)
175#define GVFAC (-51)
176#define BUFAC (128)
177
178static inline int clamp(int val, int min, int max)
179{
180 if (val < min)
181 val = min;
182 else if (val > max)
183 val = max;
184 return val;
185}
186
187void lcd_yuv_set_options(unsigned options)
188{
189 (void)options;
190}
191
192/* Draw a partial YUV colour bitmap - similiar behavior to lcd_yuv_blit
193 in the core */
194void lcd_yuv_blit(unsigned char * const src[3],
195 int src_x, int src_y, int stride,
196 int x, int y, int width, int height)
197{
198 const unsigned char *ysrc, *usrc, *vsrc;
199 int linecounter;
200 fb_data *dst, *row_end;
201 long z;
202
203 /* width and height must be >= 2 and an even number */
204 width &= ~1;
205 linecounter = height >> 1;
206
207#if LCD_WIDTH >= LCD_HEIGHT
208 dst = &lcd_framebuffer[y][x];
209 row_end = dst + width;
210#else
211 dst = &lcd_framebuffer[x][LCD_WIDTH - y - 1];
212 row_end = dst + LCD_WIDTH * width;
213#endif
214
215 z = stride * src_y;
216 ysrc = src[0] + z + src_x;
217 usrc = src[1] + (z >> 2) + (src_x >> 1);
218 vsrc = src[2] + (usrc - src[1]);
219
220 /* stride => amount to jump from end of last row to start of next */
221 stride -= width;
222
223 /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
224
225 do
226 {
227 do
228 {
229 int y, cb, cr, rv, guv, bu, r, g, b;
230
231 y = YFAC*(*ysrc++ - 16);
232 cb = *usrc++ - 128;
233 cr = *vsrc++ - 128;
234
235 rv = RVFAC*cr;
236 guv = GUFAC*cb + GVFAC*cr;
237 bu = BUFAC*cb;
238
239 r = y + rv;
240 g = y + guv;
241 b = y + bu;
242
243 if ((unsigned)(r | g | b) > 64*256-1)
244 {
245 r = clamp(r, 0, 64*256-1);
246 g = clamp(g, 0, 64*256-1);
247 b = clamp(b, 0, 64*256-1);
248 }
249
250 *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
251
252#if LCD_WIDTH >= LCD_HEIGHT
253 dst++;
254#else
255 dst += LCD_WIDTH;
256#endif
257
258 y = YFAC*(*ysrc++ - 16);
259 r = y + rv;
260 g = y + guv;
261 b = y + bu;
262
263 if ((unsigned)(r | g | b) > 64*256-1)
264 {
265 r = clamp(r, 0, 64*256-1);
266 g = clamp(g, 0, 64*256-1);
267 b = clamp(b, 0, 64*256-1);
268 }
269
270 *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
271
272#if LCD_WIDTH >= LCD_HEIGHT
273 dst++;
274#else
275 dst += LCD_WIDTH;
276#endif
277 }
278 while (dst < row_end);
279
280 ysrc += stride;
281 usrc -= width >> 1;
282 vsrc -= width >> 1;
283
284#if LCD_WIDTH >= LCD_HEIGHT
285 row_end += LCD_WIDTH;
286 dst += LCD_WIDTH - width;
287#else
288 row_end -= 1;
289 dst -= LCD_WIDTH*width + 1;
290#endif
291
292 do
293 {
294 int y, cb, cr, rv, guv, bu, r, g, b;
295
296 y = YFAC*(*ysrc++ - 16);
297 cb = *usrc++ - 128;
298 cr = *vsrc++ - 128;
299
300 rv = RVFAC*cr;
301 guv = GUFAC*cb + GVFAC*cr;
302 bu = BUFAC*cb;
303
304 r = y + rv;
305 g = y + guv;
306 b = y + bu;
307
308 if ((unsigned)(r | g | b) > 64*256-1)
309 {
310 r = clamp(r, 0, 64*256-1);
311 g = clamp(g, 0, 64*256-1);
312 b = clamp(b, 0, 64*256-1);
313 }
314
315 *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
316
317#if LCD_WIDTH >= LCD_HEIGHT
318 dst++;
319#else
320 dst += LCD_WIDTH;
321#endif
322
323 y = YFAC*(*ysrc++ - 16);
324 r = y + rv;
325 g = y + guv;
326 b = y + bu;
327
328 if ((unsigned)(r | g | b) > 64*256-1)
329 {
330 r = clamp(r, 0, 64*256-1);
331 g = clamp(g, 0, 64*256-1);
332 b = clamp(b, 0, 64*256-1);
333 }
334
335 *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
336
337#if LCD_WIDTH >= LCD_HEIGHT
338 dst++;
339#else
340 dst += LCD_WIDTH;
341#endif
342 }
343 while (dst < row_end);
344
345 ysrc += stride;
346 usrc += stride >> 1;
347 vsrc += stride >> 1;
348
349#if LCD_WIDTH >= LCD_HEIGHT
350 row_end += LCD_WIDTH;
351 dst += LCD_WIDTH - width;
352#else
353 row_end -= 1;
354 dst -= LCD_WIDTH*width + 1;
355#endif
356 }
357 while (--linecounter > 0);
358
359#if LCD_WIDTH >= LCD_HEIGHT
360 lcd_update_rect(x, y, width, height);
361#else
362 lcd_update_rect(y, x, height, width);
363#endif
364}
365#endif /* HAVE_LCD_COLOR */