diff options
Diffstat (limited to 'firmware/drivers/lcd-h300.c')
-rw-r--r-- | firmware/drivers/lcd-h300.c | 179 |
1 files changed, 48 insertions, 131 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); |