diff options
Diffstat (limited to 'firmware/target/arm/ipod/lcd-color_nano.c')
-rw-r--r-- | firmware/target/arm/ipod/lcd-color_nano.c | 132 |
1 files changed, 30 insertions, 102 deletions
diff --git a/firmware/target/arm/ipod/lcd-color_nano.c b/firmware/target/arm/ipod/lcd-color_nano.c index 7d004cb0f2..e3b9ea8eb6 100644 --- a/firmware/target/arm/ipod/lcd-color_nano.c +++ b/firmware/target/arm/ipod/lcd-color_nano.c | |||
@@ -121,38 +121,14 @@ void lcd_init_device(void) | |||
121 | } | 121 | } |
122 | 122 | ||
123 | /*** update functions ***/ | 123 | /*** update functions ***/ |
124 | extern void lcd_yuv_write_inner_loop(unsigned char const * const ysrc, | ||
125 | unsigned char const * const usrc, | ||
126 | unsigned char const * const vsrc, | ||
127 | int width); | ||
124 | 128 | ||
125 | #define CSUB_X 2 | 129 | #define CSUB_X 2 |
126 | #define CSUB_Y 2 | 130 | #define CSUB_Y 2 |
127 | 131 | ||
128 | /* YUV- > RGB565 conversion | ||
129 | * |R| |1.000000 -0.000001 1.402000| |Y'| | ||
130 | * |G| = |1.000000 -0.334136 -0.714136| |Pb| | ||
131 | * |B| |1.000000 1.772000 0.000000| |Pr| | ||
132 | * Scaled, normalized, rounded and tweaked to yield RGB 565: | ||
133 | * |R| |74 0 101| |Y' - 16| >> 9 | ||
134 | * |G| = |74 -24 -51| |Cb - 128| >> 8 | ||
135 | * |B| |74 128 0| |Cr - 128| >> 9 | ||
136 | */ | ||
137 | |||
138 | #define RGBYFAC 74 /* 1.0 */ | ||
139 | #define RVFAC 101 /* 1.402 */ | ||
140 | #define GVFAC (-51) /* -0.714136 */ | ||
141 | #define GUFAC (-24) /* -0.334136 */ | ||
142 | #define BUFAC 128 /* 1.772 */ | ||
143 | |||
144 | /* ROUNDOFFS contain constant for correct round-offs as well as | ||
145 | constant parts of the conversion matrix (e.g. (Y'-16)*RGBYFAC | ||
146 | -> constant part = -16*RGBYFAC). Through extraction of these | ||
147 | constant parts we save at leat 4 substractions in the conversion | ||
148 | loop */ | ||
149 | #define ROUNDOFFSR (256 - 16*RGBYFAC - 128*RVFAC) | ||
150 | #define ROUNDOFFSG (128 - 16*RGBYFAC - 128*GVFAC - 128*GUFAC) | ||
151 | #define ROUNDOFFSB (256 - 16*RGBYFAC - 128*BUFAC) | ||
152 | |||
153 | #define MAX_5BIT 0x1f | ||
154 | #define MAX_6BIT 0x3f | ||
155 | |||
156 | /* Performance function to blit a YUV bitmap directly to the LCD */ | 132 | /* Performance function to blit a YUV bitmap directly to the LCD */ |
157 | void lcd_blit_yuv(unsigned char * const src[3], | 133 | void lcd_blit_yuv(unsigned char * const src[3], |
158 | int src_x, int src_y, int stride, | 134 | int src_x, int src_y, int stride, |
@@ -222,7 +198,8 @@ void lcd_blit_yuv(unsigned char * const src[3], | |||
222 | const int stride_div_csub_x = stride/CSUB_X; | 198 | const int stride_div_csub_x = stride/CSUB_X; |
223 | 199 | ||
224 | h=0; | 200 | h=0; |
225 | while (1) { | 201 | while (1) |
202 | { | ||
226 | /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */ | 203 | /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */ |
227 | const unsigned char *ysrc = src[0] + stride * src_y + src_x; | 204 | const unsigned char *ysrc = src[0] + stride * src_y + src_x; |
228 | 205 | ||
@@ -231,17 +208,11 @@ void lcd_blit_yuv(unsigned char * const src[3], | |||
231 | 208 | ||
232 | const unsigned char *usrc = src[1] + uvoffset; | 209 | const unsigned char *usrc = src[1] + uvoffset; |
233 | const unsigned char *vsrc = src[2] + uvoffset; | 210 | const unsigned char *vsrc = src[2] + uvoffset; |
234 | const unsigned char *row_end = ysrc + width; | ||
235 | |||
236 | int yp, up, vp; | ||
237 | int red1, green1, blue1; | ||
238 | int red2, green2, blue2; | ||
239 | 211 | ||
240 | int rc, gc, bc; | ||
241 | int pixels_to_write; | 212 | int pixels_to_write; |
242 | fb_data pixel1,pixel2; | ||
243 | 213 | ||
244 | if (h==0) { | 214 | if (h==0) |
215 | { | ||
245 | while (!(LCD2_BLOCK_CTRL & LCD2_BLOCK_READY)); | 216 | while (!(LCD2_BLOCK_CTRL & LCD2_BLOCK_READY)); |
246 | LCD2_BLOCK_CONFIG = 0; | 217 | LCD2_BLOCK_CONFIG = 0; |
247 | 218 | ||
@@ -251,7 +222,8 @@ void lcd_blit_yuv(unsigned char * const src[3], | |||
251 | h = height; | 222 | h = height; |
252 | 223 | ||
253 | /* calculate how much we can do in one go */ | 224 | /* calculate how much we can do in one go */ |
254 | if (pixels_to_write > 0x10000) { | 225 | if (pixels_to_write > 0x10000) |
226 | { | ||
255 | h = (0x10000/2) / width; | 227 | h = (0x10000/2) / width; |
256 | pixels_to_write = (width * h) * 2; | 228 | pixels_to_write = (width * h) * 2; |
257 | } | 229 | } |
@@ -262,61 +234,7 @@ void lcd_blit_yuv(unsigned char * const src[3], | |||
262 | LCD2_BLOCK_CTRL = 0x34000000; | 234 | LCD2_BLOCK_CTRL = 0x34000000; |
263 | } | 235 | } |
264 | 236 | ||
265 | do | 237 | lcd_yuv_write_inner_loop(ysrc,usrc,vsrc,width); |
266 | { | ||
267 | up = *usrc++; | ||
268 | vp = *vsrc++; | ||
269 | rc = RVFAC * vp + ROUNDOFFSR; | ||
270 | gc = GVFAC * vp + GUFAC * up + ROUNDOFFSG; | ||
271 | bc = BUFAC * up + ROUNDOFFSB; | ||
272 | |||
273 | /* Pixel 1 -> RGB565 */ | ||
274 | yp = *ysrc++ * RGBYFAC; | ||
275 | red1 = (yp + rc) >> 9; | ||
276 | green1 = (yp + gc) >> 8; | ||
277 | blue1 = (yp + bc) >> 9; | ||
278 | |||
279 | /* Pixel 2 -> RGB565 */ | ||
280 | yp = *ysrc++ * RGBYFAC; | ||
281 | red2 = (yp + rc) >> 9; | ||
282 | green2 = (yp + gc) >> 8; | ||
283 | blue2 = (yp + bc) >> 9; | ||
284 | |||
285 | /* Since out of bounds errors are relatively rare, we check two | ||
286 | pixels at once to see if any components are out of bounds, and | ||
287 | then fix whichever is broken. This works due to high values and | ||
288 | negative values both being !=0 when bitmasking them. | ||
289 | We first check for red and blue components (5bit range). */ | ||
290 | if ((red1 | blue1 | red2 | blue2) & ~MAX_5BIT) | ||
291 | { | ||
292 | if (red1 & ~MAX_5BIT) | ||
293 | red1 = (red1 >> 31) ? 0 : MAX_5BIT; | ||
294 | if (blue1 & ~MAX_5BIT) | ||
295 | blue1 = (blue1 >> 31) ? 0 : MAX_5BIT; | ||
296 | if (red2 & ~MAX_5BIT) | ||
297 | red2 = (red2 >> 31) ? 0 : MAX_5BIT; | ||
298 | if (blue2 & ~MAX_5BIT) | ||
299 | blue2 = (blue2 >> 31) ? 0 : MAX_5BIT; | ||
300 | } | ||
301 | /* We second check for green component (6bit range) */ | ||
302 | if ((green1 | green2) & ~MAX_6BIT) | ||
303 | { | ||
304 | if (green1 & ~MAX_6BIT) | ||
305 | green1 = (green1 >> 31) ? 0 : MAX_6BIT; | ||
306 | if (green2 & ~MAX_6BIT) | ||
307 | green2 = (green2 >> 31) ? 0 : MAX_6BIT; | ||
308 | } | ||
309 | |||
310 | pixel1 = swap16((red1 << 11) | (green1 << 5) | blue1); | ||
311 | |||
312 | pixel2 = swap16((red2 << 11) | (green2 << 5) | blue2); | ||
313 | |||
314 | while (!(LCD2_BLOCK_CTRL & LCD2_BLOCK_TXOK)); | ||
315 | |||
316 | /* output 2 pixels */ | ||
317 | LCD2_BLOCK_DATA = (pixel2 << 16) | pixel1; | ||
318 | } | ||
319 | while (ysrc < row_end); | ||
320 | 238 | ||
321 | src_y++; | 239 | src_y++; |
322 | h--; | 240 | h--; |
@@ -415,16 +333,26 @@ void lcd_update_rect(int x, int y, int width, int height) | |||
415 | LCD2_BLOCK_CONFIG = 0xc0010000 | (pixels_to_write - 1); | 333 | LCD2_BLOCK_CONFIG = 0xc0010000 | (pixels_to_write - 1); |
416 | LCD2_BLOCK_CTRL = 0x34000000; | 334 | LCD2_BLOCK_CTRL = 0x34000000; |
417 | 335 | ||
418 | /* for each row */ | 336 | if (LCD_WIDTH == width) { |
419 | for (r = 0; r < h; r++) { | 337 | /* for each row and column in a single loop */ |
420 | /* for each column */ | 338 | for (r = 0; r < h*width; r += 2) { |
421 | for (c = 0; c < width; c += 2) { | 339 | while (!(LCD2_BLOCK_CTRL & LCD2_BLOCK_TXOK)); |
422 | while (!(LCD2_BLOCK_CTRL & LCD2_BLOCK_TXOK)); | 340 | |
423 | 341 | /* output 2 pixels */ | |
424 | /* output 2 pixels */ | 342 | LCD2_BLOCK_DATA = *addr++; |
425 | LCD2_BLOCK_DATA = *addr++; | 343 | } |
344 | } else { | ||
345 | /* for each row */ | ||
346 | for (r = 0; r < h; r++) { | ||
347 | /* for each column */ | ||
348 | for (c = 0; c < width; c += 2) { | ||
349 | while (!(LCD2_BLOCK_CTRL & LCD2_BLOCK_TXOK)); | ||
350 | |||
351 | /* output 2 pixels */ | ||
352 | LCD2_BLOCK_DATA = *addr++; | ||
353 | } | ||
354 | addr += (LCD_WIDTH - width)/2; | ||
426 | } | 355 | } |
427 | addr += (LCD_WIDTH - width)/2; | ||
428 | } | 356 | } |
429 | 357 | ||
430 | while (!(LCD2_BLOCK_CTRL & LCD2_BLOCK_READY)); | 358 | while (!(LCD2_BLOCK_CTRL & LCD2_BLOCK_READY)); |