diff options
Diffstat (limited to 'firmware/drivers')
-rw-r--r-- | firmware/drivers/lcd-h300.c | 179 | ||||
-rwxr-xr-x | firmware/drivers/lcd.S | 95 |
2 files changed, 48 insertions, 226 deletions
diff --git a/firmware/drivers/lcd-h300.c b/firmware/drivers/lcd-h300.c index c3f5d48f87..41d2d11509 100644 --- a/firmware/drivers/lcd-h300.c +++ b/firmware/drivers/lcd-h300.c | |||
@@ -301,134 +301,59 @@ void lcd_blit(const fb_data* data, int x, int by, int width, | |||
301 | /*if(display_on)*/ | 301 | /*if(display_on)*/ |
302 | } | 302 | } |
303 | 303 | ||
304 | #define CSUB_X 2 | 304 | /* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. |
305 | #define CSUB_Y 2 | 305 | * y should have two lines of Y back to back. |
306 | 306 | * bu and rv should contain the Cb and Cr data for the two lines of Y. | |
307 | #define RYFAC (31*257) | 307 | * Stores bu, guv and rv in repective buffers for use in second line. |
308 | #define GYFAC (63*257) | 308 | */ |
309 | #define BYFAC (31*257) | 309 | extern void lcd_write_yuv420_lines(const unsigned char *y, |
310 | #define RVFAC 11170 /* 31 * 257 * 1.402 */ | 310 | unsigned char *bu, unsigned char *guv, unsigned char *rv, int width); |
311 | #define GVFAC (-11563) /* 63 * 257 * -0.714136 */ | 311 | |
312 | #define GUFAC (-5572) /* 63 * 257 * -0.344136 */ | 312 | /* Performance function to blit a YUV bitmap directly to the LCD |
313 | #define BUFAC 14118 /* 31 * 257 * 1.772 */ | 313 | * src_x, src_y, width and height should be even |
314 | 314 | * x, y, width and height have to be within LCD bounds | |
315 | #define ROUNDOFFS (127*257) | 315 | */ |
316 | |||
317 | /* Performance function to blit a YUV bitmap directly to the LCD */ | ||
318 | void lcd_yuv_blit(unsigned char * const src[3], | 316 | void lcd_yuv_blit(unsigned char * const src[3], |
319 | int src_x, int src_y, int stride, | 317 | int src_x, int src_y, int stride, |
320 | int x, int y, int width, int height) | 318 | int x, int y, int width, int height) |
321 | { | 319 | { |
322 | if (display_on) | 320 | /* IRAM Y, Cb/bu, guv and Cb/rv buffers. */ |
323 | { | 321 | unsigned char y_ibuf[LCD_WIDTH*2]; |
324 | int ymax; | 322 | unsigned char bu_ibuf[LCD_WIDTH/2]; |
325 | 323 | unsigned char guv_ibuf[LCD_WIDTH/2]; | |
326 | width = (width + 1) & ~1; | 324 | unsigned char rv_ibuf[LCD_WIDTH/2]; |
327 | height = (height + 1) & ~1; | 325 | const unsigned char *ysrc, *usrc, *vsrc; |
328 | ymax = y + height - 1; | 326 | const unsigned char *ysrc_max; |
329 | |||
330 | /* set update window */ | ||
331 | |||
332 | /* horiz ram addr */ | ||
333 | lcd_write_reg(R_HORIZ_RAM_ADDR_POS, (ymax << 8) | y); | ||
334 | |||
335 | /* vert ram addr */ | ||
336 | lcd_write_reg(R_VERT_RAM_ADDR_POS,((x+xoffset+width-1) << 8) | (x+xoffset)); | ||
337 | lcd_write_reg(R_RAM_ADDR_SET, ((x+xoffset) << 8) | y); | ||
338 | lcd_begin_write_gram(); | ||
339 | 327 | ||
340 | for (; y <= ymax; y++) | 328 | if (!display_on) |
341 | { | 329 | return; |
342 | /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */ | 330 | |
343 | const unsigned char *ysrc = src[0] + stride * src_y + src_x; | 331 | width &= ~1; /* stay on the safe side */ |
344 | const unsigned char *usrc = src[1] + (stride/CSUB_X) * (src_y/CSUB_Y) | 332 | height &= ~1; |
345 | + (src_x/CSUB_X); | 333 | |
346 | const unsigned char *vsrc = src[2] + (stride/CSUB_X) * (src_y/CSUB_Y) | 334 | /* Set start position and window */ |
347 | + (src_x/CSUB_X); | 335 | lcd_write_reg(R_VERT_RAM_ADDR_POS,((x+xoffset+width-1) << 8) | (x+xoffset)); |
348 | const unsigned char *row_end = ysrc + width; | 336 | lcd_write_reg(R_RAM_ADDR_SET, ((x+xoffset) << 8) | y); |
349 | 337 | ||
350 | int y, u, v; | 338 | lcd_begin_write_gram(); |
351 | int rc, gc, bc; | 339 | |
352 | int red, green, blue; | 340 | ysrc = src[0] + src_y * stride + src_x; |
353 | unsigned rbits, gbits, bbits; | 341 | usrc = src[1] + (src_y * stride >> 2) + (src_x >> 1); |
354 | 342 | vsrc = src[2] + (src_y * stride >> 2) + (src_x >> 1); | |
355 | do | 343 | ysrc_max = ysrc + height * stride; |
356 | { | 344 | |
357 | u = *usrc++ - 128; | 345 | do |
358 | v = *vsrc++ - 128; | 346 | { |
359 | rc = RVFAC * v + ROUNDOFFS; | 347 | memcpy(y_ibuf, ysrc, width); |
360 | gc = GVFAC * v + GUFAC * u + ROUNDOFFS; | 348 | memcpy(y_ibuf + width, ysrc + stride, width); |
361 | bc = BUFAC * u + ROUNDOFFS; | 349 | memcpy(bu_ibuf, usrc, width >> 1); |
362 | 350 | memcpy(rv_ibuf, vsrc, width >> 1); | |
363 | y = *ysrc++; | 351 | lcd_write_yuv420_lines(y_ibuf, bu_ibuf, guv_ibuf, rv_ibuf, width); |
364 | red = RYFAC * y + rc; | 352 | ysrc += 2 * stride; |
365 | green = GYFAC * y + gc; | 353 | usrc += stride >> 1; |
366 | blue = BYFAC * y + bc; | 354 | vsrc += stride >> 1; |
367 | |||
368 | if ((unsigned)red > (RYFAC*255+ROUNDOFFS)) | ||
369 | { | ||
370 | if (red < 0) | ||
371 | red = 0; | ||
372 | else | ||
373 | red = (RYFAC*255+ROUNDOFFS); | ||
374 | } | ||
375 | if ((unsigned)green > (GYFAC*255+ROUNDOFFS)) | ||
376 | { | ||
377 | if (green < 0) | ||
378 | green = 0; | ||
379 | else | ||
380 | green = (GYFAC*255+ROUNDOFFS); | ||
381 | } | ||
382 | if ((unsigned)blue > (BYFAC*255+ROUNDOFFS)) | ||
383 | { | ||
384 | if (blue < 0) | ||
385 | blue = 0; | ||
386 | else | ||
387 | blue = (BYFAC*255+ROUNDOFFS); | ||
388 | } | ||
389 | rbits = ((unsigned)red) >> 16 ; | ||
390 | gbits = ((unsigned)green) >> 16 ; | ||
391 | bbits = ((unsigned)blue) >> 16 ; | ||
392 | |||
393 | LCD_DATA = (rbits << 11) | (gbits << 5) | bbits; | ||
394 | |||
395 | y = *ysrc++; | ||
396 | red = RYFAC * y + rc; | ||
397 | green = GYFAC * y + gc; | ||
398 | blue = BYFAC * y + bc; | ||
399 | |||
400 | if ((unsigned)red > (RYFAC*255+ROUNDOFFS)) | ||
401 | { | ||
402 | if (red < 0) | ||
403 | red = 0; | ||
404 | else | ||
405 | red = (RYFAC*255+ROUNDOFFS); | ||
406 | } | ||
407 | if ((unsigned)green > (GYFAC*255+ROUNDOFFS)) | ||
408 | { | ||
409 | if (green < 0) | ||
410 | green = 0; | ||
411 | else | ||
412 | green = (GYFAC*255+ROUNDOFFS); | ||
413 | } | ||
414 | if ((unsigned)blue > (BYFAC*255+ROUNDOFFS)) | ||
415 | { | ||
416 | if (blue < 0) | ||
417 | blue = 0; | ||
418 | else | ||
419 | blue = (BYFAC*255+ROUNDOFFS); | ||
420 | } | ||
421 | rbits = ((unsigned)red) >> 16 ; | ||
422 | gbits = ((unsigned)green) >> 16 ; | ||
423 | bbits = ((unsigned)blue) >> 16 ; | ||
424 | |||
425 | LCD_DATA = (rbits << 11) | (gbits << 5) | bbits; | ||
426 | } | ||
427 | while (ysrc < row_end); | ||
428 | |||
429 | src_y++; | ||
430 | } | ||
431 | } | 355 | } |
356 | while (ysrc < ysrc_max); | ||
432 | } | 357 | } |
433 | 358 | ||
434 | /* Update the display. | 359 | /* Update the display. |
@@ -438,10 +363,6 @@ void lcd_update(void) | |||
438 | { | 363 | { |
439 | if(display_on){ | 364 | if(display_on){ |
440 | /* reset update window */ | 365 | /* reset update window */ |
441 | /* horiz ram addr: 0 - 175 */ | ||
442 | lcd_write_reg(R_HORIZ_RAM_ADDR_POS, 0xaf00); | ||
443 | |||
444 | /* vert ram addr: 0 - 219 */ | ||
445 | lcd_write_reg(R_VERT_RAM_ADDR_POS,((xoffset+219)<<8) | xoffset); | 366 | lcd_write_reg(R_VERT_RAM_ADDR_POS,((xoffset+219)<<8) | xoffset); |
446 | 367 | ||
447 | /* Copy display bitmap to hardware */ | 368 | /* Copy display bitmap to hardware */ |
@@ -467,15 +388,11 @@ void lcd_update_rect(int x, int y, int width, int height) | |||
467 | 388 | ||
468 | /* set update window */ | 389 | /* set update window */ |
469 | 390 | ||
470 | /* horiz ram addr */ | ||
471 | lcd_write_reg(R_HORIZ_RAM_ADDR_POS, (ymax << 8) | y); | ||
472 | |||
473 | /* vert ram addr */ | ||
474 | lcd_write_reg(R_VERT_RAM_ADDR_POS,((x+xoffset+width-1) << 8) | (x+xoffset)); | 391 | lcd_write_reg(R_VERT_RAM_ADDR_POS,((x+xoffset+width-1) << 8) | (x+xoffset)); |
475 | lcd_write_reg(R_RAM_ADDR_SET, ((x+xoffset) << 8) | y); | 392 | lcd_write_reg(R_RAM_ADDR_SET, ((x+xoffset) << 8) | y); |
476 | lcd_begin_write_gram(); | 393 | lcd_begin_write_gram(); |
477 | 394 | ||
478 | /* Copy specified rectangle bitmap to hardware */ | 395 | /* Copy specified rectangle bitmap to hardware */ |
479 | for (; y <= ymax; y++) | 396 | for (; y <= ymax; y++) |
480 | { | 397 | { |
481 | lcd_write_data ((unsigned short *)&lcd_framebuffer[y][x], width); | 398 | lcd_write_data ((unsigned short *)&lcd_framebuffer[y][x], width); |
diff --git a/firmware/drivers/lcd.S b/firmware/drivers/lcd.S index 8764d793c3..d9e7092c94 100755 --- a/firmware/drivers/lcd.S +++ b/firmware/drivers/lcd.S | |||
@@ -371,99 +371,4 @@ lcd_write_data: | |||
371 | nop /* 1(0/0) */ | 371 | nop /* 1(0/0) */ |
372 | bne .loop /* 2(0/0) */ | 372 | bne .loop /* 2(0/0) */ |
373 | rts | 373 | rts |
374 | #elif defined(IRIVER_H300_SERIES) | ||
375 | .section .icode,"ax",@progbits | ||
376 | |||
377 | .align 2 | ||
378 | .global lcd_write_data | ||
379 | .type lcd_write_data,@function | ||
380 | |||
381 | lcd_write_data: | ||
382 | move.l (4,%sp),%a0 /* data pointer */ | ||
383 | move.l (8,%sp),%d0 /* length in words */ | ||
384 | add.l %d0,%d0 /* words -> bytes */ | ||
385 | add.l %a0,%d0 /* -> end address */ | ||
386 | lea.l 0xf0000002,%a1 /* LCD data port */ | ||
387 | |||
388 | move.l %a0,%d1 | ||
389 | btst.l #1,%d1 /* already longword aligned? */ | ||
390 | beq.b .word1_end /* yes: skip initial word copy */ | ||
391 | |||
392 | move.w (%a0)+,(%a1) /* transfer initial word */ | ||
393 | |||
394 | .word1_end: /* now longword aligned */ | ||
395 | moveq.l #28,%d1 | ||
396 | add.l %a0,%d1 | ||
397 | and.l #0xFFFFFFF0,%d1 /* %d1 = first line bound + 16 */ | ||
398 | cmp.l %d1,%d0 /* at least one full line to send? */ | ||
399 | blo.b .long2_start /* no: skip to trailing longword handling */ | ||
400 | |||
401 | lea.l (-16,%sp),%sp /* free up some registers */ | ||
402 | movem.l %d2-%d4/%a2,(%sp) | ||
403 | |||
404 | subq.l #8,%d1 | ||
405 | subq.l #8,%d1 /* %d1 = first line bound */ | ||
406 | |||
407 | cmp.l %a0,%d1 /* any leading longwords? */ | ||
408 | bls.b .long1_end /* no: skip leading long loop */ | ||
409 | |||
410 | .long1_loop: | ||
411 | move.l (%a0)+,%d2 /* read longword */ | ||
412 | swap %d2 /* send data to LCD in correct order...*/ | ||
413 | move.w %d2,(%a1) | ||
414 | swap %d2 | ||
415 | move.w %d2,(%a1) | ||
416 | cmp.l %a0,%d1 /* run %a0 up to first line bound */ | ||
417 | bhi.b .long1_loop | ||
418 | |||
419 | .long1_end: | ||
420 | move.l %d0,%a2 | ||
421 | lea.l (-14,%a2),%a2 /* %a2 = end address - 14 (one line/pass) */ | ||
422 | |||
423 | /* burst-optimised line transfers */ | ||
424 | .line_loop: | ||
425 | movem.l (%a0),%d1-%d4 /* burst-read line */ | ||
426 | lea.l (16,%a0),%a0 /* increment address */ | ||
427 | swap %d1 /* send data to LCD in correct order... */ | ||
428 | move.w %d1,(%a1) | ||
429 | swap %d1 | ||
430 | move.w %d1,(%a1) | ||
431 | swap %d2 | ||
432 | move.w %d2,(%a1) | ||
433 | swap %d2 | ||
434 | move.w %d2,(%a1) | ||
435 | swap %d3 | ||
436 | move.w %d3,(%a1) | ||
437 | swap %d3 | ||
438 | move.w %d3,(%a1) | ||
439 | swap %d4 | ||
440 | move.w %d4,(%a1) | ||
441 | swap %d4 | ||
442 | move.w %d4,(%a1) | ||
443 | cmp.l %a0,%a2 /* run %a0 up to last line bound */ | ||
444 | bhi.b .line_loop | ||
445 | |||
446 | movem.l (%sp),%d2-%d4/%a2 | ||
447 | lea.l (16,%sp),%sp /* restore registers */ | ||
448 | |||
449 | .long2_start: | ||
450 | subq.l #2,%d0 /* account for handling 2 words per loop */ | ||
451 | cmp.l %a0,%d0 /* any (trailing longwords? */ | ||
452 | bls.b .long2_end /* no: skip trailing longword loop */ | ||
453 | |||
454 | .long2_loop: | ||
455 | move.l (%a0)+,%d1 /* read longword */ | ||
456 | swap %d1 /* send data to LCD in correct order */ | ||
457 | move.w %d1,(%a1) | ||
458 | swap %d1 | ||
459 | move.w %d1,(%a1) | ||
460 | cmp.l %a0,%d0 /* run %a0 up to last long bound */ | ||
461 | bhi.b .long2_loop | ||
462 | |||
463 | .long2_end: | ||
464 | blo.b .word2_end /* no final word: skip */ | ||
465 | move.w (%a0)+,(%a1) /* transfer final word */ | ||
466 | |||
467 | .word2_end: | ||
468 | rts | ||
469 | #endif | 374 | #endif |