diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2007-09-25 02:59:42 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2007-09-25 02:59:42 +0000 |
commit | 287d6223d3e4f90043e5fd36cf49d7267b53023d (patch) | |
tree | 04771c28f2b826099805f5a5ad98b8c4e41091cc | |
parent | 24327ddf7ba62c873bd392fa5abe5c341b4a47b9 (diff) | |
download | rockbox-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.c | 6 | ||||
-rw-r--r-- | apps/plugin.h | 8 | ||||
-rw-r--r-- | apps/plugins/mpegplayer/SOURCES | 3 | ||||
-rw-r--r-- | apps/plugins/mpegplayer/mpeg_settings.c | 106 | ||||
-rw-r--r-- | apps/plugins/mpegplayer/mpeg_settings.h | 3 | ||||
-rw-r--r-- | apps/plugins/mpegplayer/video_out_rockbox.c | 204 | ||||
-rw-r--r-- | firmware/SOURCES | 4 | ||||
-rw-r--r-- | firmware/export/lcd.h | 4 | ||||
-rw-r--r-- | firmware/target/arm/lcd-as-memframe.S | 554 | ||||
-rw-r--r-- | firmware/target/arm/s3c2440/gigabeat-fx/lcd-as-meg-fx.S | 279 | ||||
-rw-r--r-- | firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c | 45 | ||||
-rw-r--r-- | firmware/target/arm/sandisk/sansa-e200/lcd-as-e200.S | 279 | ||||
-rw-r--r-- | firmware/target/arm/sandisk/sansa-e200/lcd-e200.c | 45 | ||||
-rw-r--r-- | uisimulator/sdl/lcd-bitmap.c | 204 |
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 | ||
510 | int plugin_load(const char* plugin, void* parameter) | 514 | int 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 @@ | |||
1 | alloc.c | 1 | alloc.c |
2 | decode.c | 2 | decode.c |
3 | header.c | 3 | header.c |
4 | idct.c | ||
5 | 4 | ||
6 | motion_comp.c | 5 | motion_comp.c |
7 | 6 | ||
8 | #ifdef CPU_ARM | 7 | #ifdef CPU_ARM |
8 | idct_arm_c.c | ||
9 | motion_comp_arm_c.c | 9 | motion_comp_arm_c.c |
10 | motion_comp_arm_s.S | 10 | motion_comp_arm_s.S |
11 | #else /* other CPU or SIM */ | 11 | #else /* other CPU or SIM */ |
12 | idct.c | ||
12 | motion_comp_c.c | 13 | motion_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; | |||
9 | struct mpeg_settings settings; | 9 | struct mpeg_settings settings; |
10 | static struct mpeg_settings old_settings; | 10 | static 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 | ||
16 | static char* showfps_options[] = {"No", "Yes"}; | ||
17 | static char* limitfps_options[] = {"No", "Yes"}; | ||
18 | static char* skipframes_options[] = {"No", "Yes"}; | ||
19 | |||
20 | static struct configdata config[] = | 16 | static 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 | |||
30 | enum 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 | |||
42 | static 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) | ||
48 | static 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 | |||
58 | static 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 | |||
27 | bool mpeg_menu(void) | 71 | bool 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 | ||
110 | void save_settings(void) | 168 | void 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 | ||
10 | extern struct mpeg_settings settings; | 13 | extern 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; | |||
40 | static int output_width; | 40 | static int output_width; |
41 | static int output_height; | 41 | static 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 | |||
60 | static 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 */ | ||
71 | static 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 | |||
237 | void vo_draw_frame (uint8_t * const * buf) | 43 | void 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 |
410 | target/arm/lcd-as-memframe.S | ||
410 | target/arm/sandisk/ata-c200_e200.c | 411 | target/arm/sandisk/ata-c200_e200.c |
411 | target/arm/sandisk/sansa-e200/lcd-e200.c | 412 | target/arm/sandisk/sansa-e200/lcd-e200.c |
412 | target/arm/sandisk/sansa-e200/lcd-as-e200.S | ||
413 | target/arm/sandisk/adc-c200_e200.c | 413 | target/arm/sandisk/adc-c200_e200.c |
414 | target/arm/sandisk/backlight-c200_e200.c | 414 | target/arm/sandisk/backlight-c200_e200.c |
415 | target/arm/usb-fw-pp502x.c | 415 | target/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 |
575 | target/arm/lcd-as-memframe.S | ||
575 | target/arm/s3c2440/gigabeat-fx/adc-meg-fx.c | 576 | target/arm/s3c2440/gigabeat-fx/adc-meg-fx.c |
576 | target/arm/s3c2440/gigabeat-fx/ata-meg-fx.c | 577 | target/arm/s3c2440/gigabeat-fx/ata-meg-fx.c |
577 | target/arm/s3c2440/gigabeat-fx/backlight-meg-fx.c | 578 | target/arm/s3c2440/gigabeat-fx/backlight-meg-fx.c |
578 | target/arm/s3c2440/gigabeat-fx/button-meg-fx.c | 579 | target/arm/s3c2440/gigabeat-fx/button-meg-fx.c |
579 | target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.c | 580 | target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.c |
580 | target/arm/s3c2440/gigabeat-fx/kernel-meg-fx.c | 581 | target/arm/s3c2440/gigabeat-fx/kernel-meg-fx.c |
581 | target/arm/s3c2440/gigabeat-fx/lcd-as-meg-fx.S | ||
582 | target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c | 582 | target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c |
583 | target/arm/s3c2440/gigabeat-fx/power-meg-fx.c | 583 | target/arm/s3c2440/gigabeat-fx/power-meg-fx.c |
584 | target/arm/s3c2440/gigabeat-fx/powermgmt-meg-fx.c | 584 | target/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); | |||
84 | extern void lcd_puts_scroll_style(int x, int y, const unsigned char* string, | 84 | extern 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 | ||
89 | extern void lcd_yuv_set_options(unsigned options); | ||
88 | extern void lcd_yuv_blit(unsigned char * const src[3], | 90 | extern 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 | ||
37 | lcd_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 | ||
41 | 10: @ 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 | ||
51 | 20: @ 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 } @ | ||
88 | 25: @ copy up done @ | ||
89 | ble 40f @ finish line @ no 32-byte segments remaining? | ||
90 | 30: @ 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 @ | ||
95 | 40: @ 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 | ||
129 | lcd_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 @ | ||
140 | 10: @ 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 @ | ||
185 | 15: @ 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 @ | ||
214 | 15: @ 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 @ | ||
243 | 15: @ 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 @ | ||
272 | 15: @ 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 | ||
319 | lcd_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 | ||
337 | 10: @ 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 @ | ||
399 | 15: @ 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 @ | ||
445 | 15: @ 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 @ | ||
493 | 15: @ 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 @ | ||
539 | 15: @ 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 | ||
35 | lcd_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 | ||
39 | 10: @ 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 | ||
49 | 20: @ 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 } @ | ||
86 | 25: @ copy up done @ | ||
87 | ble 40f @ finish line @ no 32-byte segments remaining? | ||
88 | 30: @ 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 @ | ||
93 | 40: @ 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 | ||
126 | lcd_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 | ||
136 | 10: @ 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 @ | ||
181 | 15: @ 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 @ | ||
209 | 15: @ 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 @ | ||
238 | 15: @ 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 @ | ||
266 | 15: @ 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 | ||
10 | static volatile bool lcd_on = true; | 10 | static volatile bool lcd_on = true; |
11 | volatile bool lcd_poweroff = false; | 11 | volatile bool lcd_poweroff = false; |
12 | static 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 | ||
252 | void 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. */ |
252 | extern void lcd_write_yuv420_lines(fb_data *dst, | 258 | extern 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); |
262 | extern 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 | ||
293 | void lcd_set_contrast(int val) { | 322 | void 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 | ||
35 | lcd_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 | ||
39 | 10: @ 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 | ||
49 | 20: @ 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 } @ | ||
86 | 25: @ copy up done @ | ||
87 | ble 40f @ finish line @ no 32-byte segments remaining? | ||
88 | 30: @ 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 @ | ||
93 | 40: @ 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 | ||
126 | lcd_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 | ||
136 | 10: @ 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 @ | ||
181 | 15: @ 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 @ | ||
209 | 15: @ 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 @ | ||
238 | 15: @ 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 @ | ||
266 | 15: @ 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 */ |
30 | static bool power_on = false; /* Is the power turned on? */ | 30 | static bool power_on = false; /* Is the power turned on? */ |
31 | static bool display_on NOCACHEBSS_ATTR = false; /* Is the display turned on? */ | 31 | static bool display_on NOCACHEBSS_ATTR = false; /* Is the display turned on? */ |
32 | static 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 | ||
629 | void 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. */ |
629 | extern void lcd_write_yuv420_lines(fb_data *dst, | 635 | extern 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); |
639 | extern 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 | |||
178 | static 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 | |||
187 | void 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 */ | ||
194 | void 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 */ | ||