summaryrefslogtreecommitdiff
path: root/firmware/target/arm/ipod/video
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/ipod/video')
-rw-r--r--firmware/target/arm/ipod/video/lcd-video.c206
1 files changed, 91 insertions, 115 deletions
diff --git a/firmware/target/arm/ipod/video/lcd-video.c b/firmware/target/arm/ipod/video/lcd-video.c
index 237162b664..27f31c3511 100644
--- a/firmware/target/arm/ipod/video/lcd-video.c
+++ b/firmware/target/arm/ipod/video/lcd-video.c
@@ -104,7 +104,7 @@ static void lcd_bcm_setup_rect(unsigned cmd,
104 lcd_bcm_write32(0xE001C, 0); 104 lcd_bcm_write32(0xE001C, 0);
105} 105}
106 106
107static unsigned lcd_bcm_read32(unsigned address) { 107static inline unsigned lcd_bcm_read32(unsigned address) {
108 while ((inw(0x30020000) & 1) == 0); 108 while ((inw(0x30020000) & 1) == 0);
109 109
110 /* write out destination address as two 16bit values */ 110 /* write out destination address as two 16bit values */
@@ -205,27 +205,39 @@ void lcd_update(void)
205 lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); 205 lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT);
206} 206}
207 207
208#define CSUB_X 2 208/* YUV- > RGB565 conversion
209#define CSUB_Y 2 209 * |R| |1.000000 -0.000001 1.402000| |Y'|
210 210 * |G| = |1.000000 -0.334136 -0.714136| |Pb|
211#define RYFAC (31*257) 211 * |B| |1.000000 1.772000 0.000000| |Pr|
212#define GYFAC (31*257) 212 * Scaled, normalized, rounded and tweaked to yield RGB 565:
213#define BYFAC (31*257) 213 * |R| |74 0 101| |Y' - 16| >> 9
214#define RVFAC 11170 /* 31 * 257 * 1.402 */ 214 * |G| = |74 -24 -51| |Cb - 128| >> 8
215#define GVFAC (-5690) /* 31 * 257 * -0.714136 */ 215 * |B| |74 128 0| |Cr - 128| >> 9
216#define GUFAC (-2742) /* 31 * 257 * -0.344136 */ 216*/
217#define BUFAC 14118 /* 31 * 257 * 1.772 */ 217
218 218#define RGBYFAC 74 /* 1.0 */
219#define ROUNDOFFS (127*257) 219#define RVFAC 101 /* 1.402 */
220#define ROUNDOFFSG (63*257) 220#define GVFAC (-51) /* -0.714136 */
221#define GUFAC (-24) /* -0.334136 */
222#define BUFAC 128 /* 1.772 */
223
224/* ROUNDOFFS contain constant for correct round-offs as well as
225 constant parts of the conversion matrix (e.g. (Y'-16)*RGBYFAC
226 -> constant part = -16*RGBYFAC). Through extraction of these
227 constant parts we save at leat 4 substractions in the conversion
228 loop */
229#define ROUNDOFFSR (256 - 16*RGBYFAC - 128*RVFAC)
230#define ROUNDOFFSG (128 - 16*RGBYFAC - 128*GVFAC - 128*GUFAC)
231#define ROUNDOFFSB (256 - 16*RGBYFAC - 128*BUFAC)
232
233#define MAX_5BIT 0x1f
234#define MAX_6BIT 0x3f
221 235
222/* Performance function to blit a YUV bitmap directly to the LCD */ 236/* Performance function to blit a YUV bitmap directly to the LCD */
223void lcd_yuv_blit(unsigned char * const src[3], 237void lcd_yuv_blit(unsigned char * const src[3],
224 int src_x, int src_y, int stride, 238 int src_x, int src_y, int stride,
225 int x, int y, int width, int height) 239 int x, int y, int width, int height)
226{ 240{
227 int ymax;
228
229 width = (width + 1) & ~1; 241 width = (width + 1) & ~1;
230 242
231 if (finishup_needed) { 243 if (finishup_needed) {
@@ -261,119 +273,83 @@ void lcd_yuv_blit(unsigned char * const src[3],
261 /* wait for it to be write ready */ 273 /* wait for it to be write ready */
262 while ((inw(0x30030000) & 0x2) == 0); 274 while ((inw(0x30030000) & 0x2) == 0);
263 275
264 ymax = y + height - 1 ; 276 const int ymax = y + height - 1;
265 277 const int stride_div_sub_x = stride >> 1;
266 const int stride_div_csub_x = stride/CSUB_X; 278 unsigned char *ysrc = 0;
279 unsigned char *usrc = 0;
280 unsigned char *vsrc = 0;
281 unsigned char *row_end = 0;
282 int uvoffset;
283 int yp, up, vp, rc, gc, bc; /* temporary variables */
284 int red1, green1, blue1; /* contain RGB of 1st pixel */
285 int red2, green2, blue2; /* contain RGB of 2nd pixel */
267 286
268 for (; y <= ymax ; y++) 287 for (; y <= ymax ; y++)
269 { 288 {
270 /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */ 289 /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
271 const unsigned char *ysrc = src[0] + stride * src_y + src_x; 290 uvoffset = stride_div_sub_x*(src_y >> 1) + (src_x >> 1);
272 291 ysrc = src[0] + stride * src_y + src_x;
273 const int uvoffset = stride_div_csub_x * (src_y/CSUB_Y) + 292 usrc = src[1] + uvoffset;
274 (src_x/CSUB_X); 293 vsrc = src[2] + uvoffset;
275 294
276 const unsigned char *usrc = src[1] + uvoffset; 295 row_end = ysrc + width;
277 const unsigned char *vsrc = src[2] + uvoffset;
278 const unsigned char *row_end = ysrc + width;
279
280 int y, u, v;
281 int red1, green1, blue1;
282 int red2, green2, blue2;
283 unsigned rbits, gbits, bbits;
284
285 int rc, gc, bc;
286 296
287 do 297 do
288 { 298 {
289 u = *usrc++ - 128; 299 up = *usrc++;
290 v = *vsrc++ - 128; 300 vp = *vsrc++;
291 rc = RVFAC * v + ROUNDOFFS; 301 rc = RVFAC * vp + ROUNDOFFSR;
292 gc = GVFAC * v + GUFAC * u + ROUNDOFFSG; 302 gc = GVFAC * vp + GUFAC * up + ROUNDOFFSG;
293 bc = BUFAC * u + ROUNDOFFS; 303 bc = BUFAC * up + ROUNDOFFSB;
294 304
295 /* Pixel 1 */ 305 /* Pixel 1 -> RGB565 */
296 y = *ysrc++; 306 yp = *ysrc++ * RGBYFAC;
297 307 red1 = (yp + rc) >> 9;
298 red1 = RYFAC * y + rc; 308 green1 = (yp + gc) >> 8;
299 green1 = GYFAC * y + gc; 309 blue1 = (yp + bc) >> 9;
300 blue1 = BYFAC * y + bc; 310
301 311 /* Pixel 2 -> RGB565 */
302 /* Pixel 2 */ 312 yp = *ysrc++ * RGBYFAC;
303 y = *ysrc++; 313 red2 = (yp + rc) >> 9;
304 red2 = RYFAC * y + rc; 314 green2 = (yp + gc) >> 8;
305 green2 = GYFAC * y + gc; 315 blue2 = (yp + bc) >> 9;
306 blue2 = BYFAC * y + bc; 316
307
308 /* Since out of bounds errors are relatively rare, we check two 317 /* Since out of bounds errors are relatively rare, we check two
309 pixels at once to see if any components are out of bounds, and 318 pixels at once to see if any components are out of bounds, and
310 then fix whichever is broken. This works due to high values and 319 then fix whichever is broken. This works due to high values and
311 negative values both becoming larger than the cutoff when 320 negative values both being !=0 when bitmasking them.
312 casted to unsigned. And ORing them together checks all of them 321 We first check for red and blue components (5bit range). */
313 simultaneously. */ 322 if ((red1 | blue1 | red2 | blue2) & ~MAX_5BIT)
314 if (((unsigned)(red1 | green1 | blue1 | 323 {
315 red2 | green2 | blue2)) > (RYFAC*255+ROUNDOFFS)) { 324 if ((red1 | blue1) & ~MAX_5BIT)
316 if (((unsigned)(red1 | green1 | blue1)) > 325 {
317 (RYFAC*255+ROUNDOFFS)) { 326 if (red1 & ~MAX_5BIT)
318 if ((unsigned)red1 > (RYFAC*255+ROUNDOFFS)) 327 red1 = (red1 >> 31) ? 0 : MAX_5BIT;
319 { 328 if (blue1 & ~MAX_5BIT)
320 if (red1 < 0) 329 blue1 = (blue1 >> 31) ? 0 : MAX_5BIT;
321 red1 = 0;
322 else
323 red1 = (RYFAC*255+ROUNDOFFS);
324 }
325 if ((unsigned)green1 > (GYFAC*255+ROUNDOFFSG))
326 {
327 if (green1 < 0)
328 green1 = 0;
329 else
330 green1 = (GYFAC*255+ROUNDOFFSG);
331 }
332 if ((unsigned)blue1 > (BYFAC*255+ROUNDOFFS))
333 {
334 if (blue1 < 0)
335 blue1 = 0;
336 else
337 blue1 = (BYFAC*255+ROUNDOFFS);
338 }
339 } 330 }
340 331 if ((red2 | blue2) & ~MAX_5BIT)
341 if (((unsigned)(red2 | green2 | blue2)) > 332 {
342 (RYFAC*255+ROUNDOFFS)) { 333 if (red2 & ~MAX_5BIT)
343 if ((unsigned)red2 > (RYFAC*255+ROUNDOFFS)) 334 red2 = (red2 >> 31) ? 0 : MAX_5BIT;
344 { 335 if (blue2 & ~MAX_5BIT)
345 if (red2 < 0) 336 blue2 = (blue2 >> 31) ? 0 : MAX_5BIT;
346 red2 = 0;
347 else
348 red2 = (RYFAC*255+ROUNDOFFS);
349 }
350 if ((unsigned)green2 > (GYFAC*255+ROUNDOFFSG))
351 {
352 if (green2 < 0)
353 green2 = 0;
354 else
355 green2 = (GYFAC*255+ROUNDOFFSG);
356 }
357 if ((unsigned)blue2 > (BYFAC*255+ROUNDOFFS))
358 {
359 if (blue2 < 0)
360 blue2 = 0;
361 else
362 blue2 = (BYFAC*255+ROUNDOFFS);
363 }
364 } 337 }
365 } 338 }
366 339 /* We second check for green component (6bit range) */
367 rbits = red1 >> 16 ; 340 if ((green1 | green2) & ~MAX_6BIT)
368 gbits = green1 >> 15 ; 341 {
369 bbits = blue1 >> 16 ; 342 if (green1 & ~MAX_6BIT)
370 343 green1 = (green1 >> 31) ? 0 : MAX_6BIT;
371 outw((rbits << 11) | (gbits << 5) | bbits, 0x30000000); 344 if (green2 & ~MAX_6BIT)
345 green2 = (green2 >> 31) ? 0 : MAX_6BIT;
346 }
347
348 /* pixel1 */
349 outw((red1 << 11) | (green1 << 5) | blue1, 0x30000000);
372 350
373 rbits = red2 >> 16 ; 351 /* pixel2 */
374 gbits = green2 >> 15 ; 352 outw((red2 << 11) | (green2 << 5) | blue2, 0x30000000);
375 bbits = blue2 >> 16 ;
376 outw((rbits << 11) | (gbits << 5) | bbits, 0x30000000);
377 } 353 }
378 while (ysrc < row_end); 354 while (ysrc < row_end);
379 355