diff options
author | Karl Kurbjun <kkurbjun@gmail.com> | 2009-08-20 00:36:39 +0000 |
---|---|---|
committer | Karl Kurbjun <kkurbjun@gmail.com> | 2009-08-20 00:36:39 +0000 |
commit | 7b4d709f9df3115a1be11d15c1e77c59b5538d8c (patch) | |
tree | 617433273791f0e1073eaa198a9dc10377d43d47 | |
parent | 6515d7f81fa5bd03c426204e91ff17e659e2c39c (diff) | |
download | rockbox-7b4d709f9df3115a1be11d15c1e77c59b5538d8c.tar.gz rockbox-7b4d709f9df3115a1be11d15c1e77c59b5538d8c.zip |
M:Robe 500: Add support for DMA based LCD updates when in Portrait mode. TestFPS measures 190 FPS with the DMA updates vs. 58 FPS for the non-DMA updates.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@22435 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | firmware/export/dm320.h | 18 | ||||
-rw-r--r-- | firmware/target/arm/tms320dm320/mrobe-500/lcd-mr500.c | 312 |
2 files changed, 299 insertions, 31 deletions
diff --git a/firmware/export/dm320.h b/firmware/export/dm320.h index 619a77fb9a..f78fc6c6d6 100644 --- a/firmware/export/dm320.h +++ b/firmware/export/dm320.h | |||
@@ -43,6 +43,9 @@ extern unsigned long _ttbstart; | |||
43 | #define PHY_IO_BASE2 0x00060000 | 43 | #define PHY_IO_BASE2 0x00060000 |
44 | #define DM320_REG2(addr) (*(volatile unsigned int *)(PHY_IO_BASE2 + (addr))) | 44 | #define DM320_REG2(addr) (*(volatile unsigned int *)(PHY_IO_BASE2 + (addr))) |
45 | 45 | ||
46 | #define COP_IO_BASE 0x00090000 | ||
47 | #define DM320_COP(addr) (*(volatile unsigned short *)(COP_IO_BASE + (addr))) | ||
48 | |||
46 | /* This needs to be 2048 byte aligned, but USB_QHARRAY_ATTR should take care | 49 | /* This needs to be 2048 byte aligned, but USB_QHARRAY_ATTR should take care |
47 | * of that */ | 50 | * of that */ |
48 | #define USB_QHARRAY_ATTR __attribute__((section(".qharray"),nocommon,aligned(4))) | 51 | #define USB_QHARRAY_ATTR __attribute__((section(".qharray"),nocommon,aligned(4))) |
@@ -708,6 +711,21 @@ extern unsigned long _ttbstart; | |||
708 | #define VL_INTVEC30_R DM320_REG2(0x03e0) | 711 | #define VL_INTVEC30_R DM320_REG2(0x03e0) |
709 | #define VL_INTVEC74_R DM320_REG2(0x03e4) | 712 | #define VL_INTVEC74_R DM320_REG2(0x03e4) |
710 | 713 | ||
714 | /* Coprocessor Interface */ | ||
715 | #define COP_SDEM_ADDRH DM320_COP(0xe000) | ||
716 | #define COP_SDEM_ADDRL DM320_COP(0xe002) | ||
717 | #define COP_SDEM_LOFST DM320_COP(0xe004) | ||
718 | #define COP_BUF_ADDR DM320_COP(0xe006) | ||
719 | #define COP_BUF_LOFST DM320_COP(0xe008) | ||
720 | #define COP_DMA_XNUM DM320_COP(0xe00a) | ||
721 | #define COP_DMA_YNUM DM320_COP(0xe00c) | ||
722 | #define COP_DMA_CTRL DM320_COP(0xe00e) | ||
723 | #define COP_BUF_MUX0 DM320_COP(0xe010) | ||
724 | #define COP_BUF_MUX1 DM320_COP(0xe012) | ||
725 | #define COP_IMG_MODE DM320_COP(0xe014) | ||
726 | #define COP_CP_CLKC DM320_COP(0xe502) | ||
727 | |||
728 | |||
711 | /* Taken from linux/include/asm-arm/arch-itdm320/irqs.h | 729 | /* Taken from linux/include/asm-arm/arch-itdm320/irqs.h |
712 | * | 730 | * |
713 | * Copyright (C) 1999 ARM Limited | 731 | * Copyright (C) 1999 ARM Limited |
diff --git a/firmware/target/arm/tms320dm320/mrobe-500/lcd-mr500.c b/firmware/target/arm/tms320dm320/mrobe-500/lcd-mr500.c index 1e4bb85de6..ea723c1dee 100644 --- a/firmware/target/arm/tms320dm320/mrobe-500/lcd-mr500.c +++ b/firmware/target/arm/tms320dm320/mrobe-500/lcd-mr500.c | |||
@@ -30,6 +30,17 @@ | |||
30 | #include "system-target.h" | 30 | #include "system-target.h" |
31 | #include "lcd.h" | 31 | #include "lcd.h" |
32 | #include "lcd-target.h" | 32 | #include "lcd-target.h" |
33 | #include "dsp-target.h" | ||
34 | #include "dsp/ipc.h" | ||
35 | |||
36 | #if CONFIG_ORIENTATION == SCREEN_PORTRAIT | ||
37 | #define PORTRAIT_USE_DMA | ||
38 | #else | ||
39 | /* Very slow - May be faster if the DSP has lower latency access to buffer. | ||
40 | Using the DSP instead of ARM to do transformation has not been tried | ||
41 | */ | ||
42 | //#define LANDSCAPE_USE_DMA | ||
43 | #endif | ||
33 | 44 | ||
34 | /* Copies a rectangle from one framebuffer to another. Can be used in | 45 | /* Copies a rectangle from one framebuffer to another. Can be used in |
35 | single transfer mode with width = num pixels, and height = 1 which | 46 | single transfer mode with width = num pixels, and height = 1 which |
@@ -260,11 +271,206 @@ void lcd_set_mode(int mode) | |||
260 | } | 271 | } |
261 | #endif | 272 | #endif |
262 | 273 | ||
274 | #if defined(PORTRAIT_USE_DMA) | ||
275 | static void dma_start_transfer16( char *src, char *dst, int stride, | ||
276 | int width, int height, int pix_width) | ||
277 | __attribute__ ((section(".icode"))); | ||
278 | |||
279 | static void dma_start_transfer16( char *src, char *dst, int stride, | ||
280 | int width, int height, int pix_width) { | ||
281 | int c_width = width; | ||
282 | |||
283 | /* Addresses are relative to start of SDRAM */ | ||
284 | src-=CONFIG_SDRAM_START; | ||
285 | dst-=CONFIG_SDRAM_START; | ||
286 | |||
287 | /* Enable Clocks */ | ||
288 | IO_CLK_MOD1 |= 1<<8; | ||
289 | COP_CP_CLKC |= 0x0001; | ||
290 | |||
291 | /* ... */ | ||
292 | COP_BUF_MUX1 = 0x0005; | ||
293 | /* Give the DMA access to the buffer */ | ||
294 | COP_BUF_MUX0 = 0x0663; | ||
295 | |||
296 | /* Setup buffer offsets and transfer width/height */ | ||
297 | COP_BUF_LOFST = 32; | ||
298 | COP_DMA_XNUM = 32; | ||
299 | COP_DMA_YNUM = 32; | ||
300 | |||
301 | /* ... */ | ||
302 | COP_IMG_MODE = 0x0000; | ||
303 | |||
304 | /* Set the start address of buffer */ | ||
305 | COP_BUF_ADDR = 0x0000; | ||
306 | |||
307 | /* Setup SDRAM stride */ | ||
308 | COP_SDEM_LOFST = stride; | ||
309 | do { | ||
310 | do { | ||
311 | int addr; | ||
312 | addr = (int)src; | ||
313 | addr >>= 1; /* Addresses are in 16-bit words */ | ||
314 | |||
315 | /* Setup the registers to initiate the read from SDRAM */ | ||
316 | COP_SDEM_ADDRH = addr >> 16; | ||
317 | COP_SDEM_ADDRL = addr & 0xFFFF; | ||
318 | |||
319 | /* Set direction and start */ | ||
320 | COP_DMA_CTRL = 0x0001; | ||
321 | COP_DMA_CTRL |= 0x0003; | ||
322 | |||
323 | /* Wait for read to finish */ | ||
324 | while(COP_DMA_CTRL & 0x02) {}; | ||
325 | |||
326 | addr = (int)dst; | ||
327 | addr >>= 1; | ||
328 | |||
329 | COP_SDEM_ADDRH = addr >> 16; | ||
330 | COP_SDEM_ADDRL = addr & 0xFFFF; | ||
331 | |||
332 | /* Set direction and start transfer */ | ||
333 | COP_DMA_CTRL = 0x0000; | ||
334 | COP_DMA_CTRL = 0x0002; | ||
335 | |||
336 | /* Wait for the transfer to complete */ | ||
337 | while(COP_DMA_CTRL & 0x02) {}; | ||
338 | |||
339 | /* Update source and destination pointers/counters */ | ||
340 | src += 32*pix_width; | ||
341 | dst += 32*pix_width; | ||
342 | c_width -= 32; | ||
343 | } while (c_width>0); | ||
344 | |||
345 | /* Reset the width, update pointers/counters */ | ||
346 | c_width = width; | ||
347 | src -= width*pix_width; | ||
348 | dst -= width*pix_width; | ||
349 | src += (LCD_WIDTH*32*pix_width); | ||
350 | dst += (LCD_WIDTH*32*pix_width); | ||
351 | height -= 32; | ||
352 | } while(height>0); | ||
353 | } | ||
354 | #endif | ||
355 | |||
356 | #if defined(LANDSCAPE_USE_DMA) | ||
357 | static void dma_start_transfer16_r( char *src, int sx, int sy, int sstride, | ||
358 | char *dst, int dx, int dy, int dstride, | ||
359 | int width, int height, int pix_width) { | ||
360 | if(sx & 0x0F) { | ||
361 | int sx2 = sx + width; | ||
362 | |||
363 | if(sx2 & 0x0F) { | ||
364 | sx2 = (sx2 + 0x0F) & ~0x0F; | ||
365 | } | ||
366 | sx = sx & ~0x0F; | ||
367 | |||
368 | width = sx2 - sx; | ||
369 | } | ||
370 | |||
371 | if(sy & 0x0F) { | ||
372 | int sy2 = sy + height; | ||
373 | |||
374 | if(sy2 & 0x0F) { | ||
375 | sy2 = (sy2 + 0x0F) & ~0x0F; | ||
376 | } | ||
377 | sy = sy & ~0x0F; | ||
378 | |||
379 | height = sy2 - sy; | ||
380 | } | ||
381 | |||
382 | if(dx & 0x0F) { | ||
383 | dx = dx & ~0x0F; | ||
384 | } | ||
385 | |||
386 | if(dy & 0x0F) { | ||
387 | dy = dy & ~0x0F; | ||
388 | } | ||
389 | |||
390 | src=src+(sy*sstride+sx)*pix_width; | ||
391 | |||
392 | dst=dst + ((LCD_NATIVE_WIDTH*(LCD_NATIVE_HEIGHT-1)) | ||
393 | - LCD_NATIVE_WIDTH*(dx+32) + dy)*pix_width; | ||
394 | |||
395 | int c_width = width; | ||
396 | |||
397 | IO_CLK_MOD1 |= 1<<8; | ||
398 | |||
399 | COP_CP_CLKC |= 0x0001; | ||
400 | |||
401 | COP_BUF_MUX1 = 0x0005; | ||
402 | /* Give the DMA access to the buffer */ | ||
403 | COP_BUF_MUX0 = 0x0663; | ||
404 | |||
405 | /* Set the buffer offsets and widths */ | ||
406 | COP_BUF_LOFST = 32; | ||
407 | COP_DMA_XNUM = 32; | ||
408 | COP_DMA_YNUM = 32; | ||
409 | COP_IMG_MODE = 0x0000; | ||
410 | |||
411 | do { | ||
412 | char *c_dst = dst; | ||
413 | do { | ||
414 | int addr; | ||
415 | |||
416 | COP_BUF_ADDR = 0x0000; | ||
417 | |||
418 | COP_SDEM_LOFST = sstride; | ||
419 | addr = (int)src - CONFIG_SDRAM_START; | ||
420 | addr >>= 1; | ||
421 | |||
422 | COP_SDEM_ADDRH = addr >> 16; | ||
423 | COP_SDEM_ADDRL = addr & 0xFFFF; | ||
424 | |||
425 | COP_DMA_CTRL = 0x0001; | ||
426 | COP_DMA_CTRL |= 0x0003; | ||
427 | |||
428 | while(COP_DMA_CTRL & 0x02) {}; | ||
429 | |||
430 | /* The ARM can access the buffer after this is set */ | ||
431 | COP_BUF_MUX0 = 0x0660; | ||
432 | |||
433 | int run=1023; | ||
434 | #define IMG_BUF (*(volatile unsigned short *)(0x80000)) | ||
435 | #define IMG_BUF2 (*(volatile unsigned short *)(0x80000 + 2*32*32 + 32*31*2 )) | ||
436 | do { | ||
437 | *(&IMG_BUF2-((run&0x1F)<<5)+(run>>5)) = *(&IMG_BUF+run); | ||
438 | } while(run--); | ||
439 | |||
440 | COP_BUF_MUX0 = 0x0663; | ||
441 | |||
442 | COP_BUF_ADDR = (32*32); | ||
443 | |||
444 | COP_SDEM_LOFST = LCD_NATIVE_WIDTH; | ||
445 | addr = (int)c_dst - CONFIG_SDRAM_START; | ||
446 | addr >>= 1; | ||
447 | |||
448 | COP_SDEM_ADDRH = addr >> 16; | ||
449 | COP_SDEM_ADDRL = addr & 0xFFFF; | ||
450 | |||
451 | COP_DMA_CTRL = 0x0000; | ||
452 | COP_DMA_CTRL = 0x0002; | ||
453 | |||
454 | while(COP_DMA_CTRL & 0x02) {}; | ||
455 | |||
456 | src += 32*pix_width; | ||
457 | c_dst -= 32*pix_width*LCD_NATIVE_WIDTH; | ||
458 | c_width -= 32; | ||
459 | } while (c_width>0); | ||
460 | |||
461 | c_width = width; | ||
462 | src += (LCD_WIDTH*31*pix_width); | ||
463 | dst += (32*pix_width); | ||
464 | height -= 32; | ||
465 | } while(height>0); | ||
466 | } | ||
467 | #endif | ||
468 | |||
263 | /* Update a fraction of the display. */ | 469 | /* Update a fraction of the display. */ |
470 | void lcd_update_rect(int x, int y, int width, int height) | ||
471 | __attribute__ ((section(".icode"))); | ||
264 | void lcd_update_rect(int x, int y, int width, int height) | 472 | void lcd_update_rect(int x, int y, int width, int height) |
265 | { | 473 | { |
266 | register fb_data *dst, *src; | ||
267 | |||
268 | if (!lcd_on) | 474 | if (!lcd_on) |
269 | return; | 475 | return; |
270 | 476 | ||
@@ -281,76 +487,120 @@ void lcd_update_rect(int x, int y, int width, int height) | |||
281 | if (y < 0) | 487 | if (y < 0) |
282 | height += y, y = 0; /* Clip top */ | 488 | height += y, y = 0; /* Clip top */ |
283 | 489 | ||
490 | #if CONFIG_ORIENTATION == SCREEN_PORTRAIT | ||
491 | #if defined(PORTRAIT_USE_DMA) | ||
492 | /* Makes sure the update is a ratio of 32x32 */ | ||
493 | if(x & 0x1F) { | ||
494 | int x2 = x + width; | ||
495 | |||
496 | if(x2 & 0x1F) { | ||
497 | x2 = (x2 + 0x1F) & ~0x1F; | ||
498 | } | ||
499 | x = x & ~0x1F; | ||
500 | |||
501 | width = x2 - x; | ||
502 | } | ||
503 | |||
504 | if(y & 0x1F) { | ||
505 | int y2 = y + height; | ||
506 | |||
507 | if(y2 & 0x1F) { | ||
508 | y2 += 0x1F; | ||
509 | y2 &= ~0x1F; | ||
510 | } | ||
511 | y = y & ~0x1F; | ||
512 | |||
513 | height = y2 - y; | ||
514 | } | ||
515 | |||
516 | fb_data *dst; | ||
284 | 517 | ||
285 | src = &lcd_framebuffer[y][x]; | 518 | dst = (fb_data *)FRAME + LCD_WIDTH*y + x; |
519 | |||
520 | dma_start_transfer16( (char *)&lcd_framebuffer[y][x],(char *)dst, | ||
521 | LCD_WIDTH, width, height, 2); | ||
522 | #else | ||
523 | register fb_data *dst; | ||
286 | 524 | ||
287 | #if CONFIG_ORIENTATION == SCREEN_PORTRAIT | ||
288 | dst = (fb_data *)FRAME + LCD_WIDTH*y + x; | 525 | dst = (fb_data *)FRAME + LCD_WIDTH*y + x; |
289 | 526 | ||
290 | /* Copy part of the Rockbox framebuffer to the second framebuffer */ | 527 | /* Copy part of the Rockbox framebuffer to the second framebuffer */ |
291 | if (width < LCD_WIDTH) | 528 | if (width < LCD_WIDTH) |
292 | { | 529 | { |
293 | /* Not full width - do line-by-line */ | 530 | /* Not full width - do line-by-line */ |
294 | lcd_copy_buffer_rect(dst, src, width, height); | 531 | lcd_copy_buffer_rect(dst, &lcd_framebuffer[y][x], width, height); |
295 | } | 532 | } |
296 | else | 533 | else |
297 | { | 534 | { |
298 | /* Full width - copy as one line */ | 535 | /* Full width - copy as one line */ |
299 | lcd_copy_buffer_rect(dst, src, LCD_WIDTH*height, 1); | 536 | lcd_copy_buffer_rect(dst, &lcd_framebuffer[y][x], LCD_WIDTH*height, 1); |
300 | } | 537 | } |
538 | #endif | ||
301 | #else | 539 | #else |
540 | #if defined(LANDSCAPE_USE_DMA) | ||
541 | dma_start_transfer16_r( (char *)lcd_framebuffer, 0, 0, LCD_WIDTH, | ||
542 | (char *)FRAME, 0, 0, LCD_NATIVE_WIDTH, | ||
543 | LCD_WIDTH, LCD_HEIGHT, 2); | ||
544 | #else | ||
545 | register fb_data *dst, *src; | ||
546 | src = &lcd_framebuffer[y][x]; | ||
547 | |||
302 | dst=FRAME + (LCD_NATIVE_WIDTH*(LCD_NATIVE_HEIGHT-1)) | 548 | dst=FRAME + (LCD_NATIVE_WIDTH*(LCD_NATIVE_HEIGHT-1)) |
303 | - LCD_NATIVE_WIDTH*x + y ; | 549 | - LCD_NATIVE_WIDTH*x + y ; |
304 | 550 | ||
305 | while(height--) | 551 | height--; |
306 | { | 552 | do { |
307 | register int c_width=width; | 553 | register int c_width=width-1; |
308 | register fb_data *c_dst=dst; | 554 | register fb_data *c_dst=dst; |
309 | 555 | ||
310 | while(c_width--) | 556 | do { |
311 | { | ||
312 | *c_dst=*src++; | 557 | *c_dst=*src++; |
313 | c_dst-=LCD_NATIVE_WIDTH; | 558 | c_dst-=LCD_NATIVE_WIDTH; |
314 | } | 559 | } while(c_width--); |
315 | 560 | ||
316 | src+=LCD_WIDTH-width; | 561 | src+=LCD_WIDTH-width; |
317 | dst++; | 562 | dst++; |
318 | } | 563 | } while(height--); |
319 | 564 | #endif | |
320 | #endif | 565 | #endif |
321 | } | 566 | } |
322 | 567 | ||
323 | /* Update the display. | 568 | /* Update the display. |
324 | This must be called after all other LCD functions that change the display. */ | 569 | This must be called after all other LCD functions that change the display. */ |
570 | void lcd_update(void) __attribute__ ((section(".icode"))); | ||
325 | void lcd_update(void) | 571 | void lcd_update(void) |
326 | { | 572 | { |
327 | if (!lcd_on) | 573 | if (!lcd_on) |
328 | return; | 574 | return; |
329 | 575 | ||
330 | #if CONFIG_ORIENTATION == SCREEN_PORTRAIT | ||
331 | lcd_copy_buffer_rect((fb_data *)FRAME, &lcd_framebuffer[0][0], | ||
332 | LCD_WIDTH*LCD_HEIGHT, 1); | ||
333 | #else | ||
334 | lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); | 576 | lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); |
335 | #endif | ||
336 | } | 577 | } |
337 | 578 | ||
338 | #if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256) | 579 | #if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256) |
339 | void lcd_blit_pal256(unsigned char *src, int src_x, int src_y, int x, int y, | 580 | void lcd_blit_pal256(unsigned char *src, int src_x, int src_y, int x, int y, |
581 | int width, int height) __attribute__ ((section(".icode"))); | ||
582 | void lcd_blit_pal256(unsigned char *src, int src_x, int src_y, int x, int y, | ||
340 | int width, int height) | 583 | int width, int height) |
341 | { | 584 | { |
342 | #if CONFIG_ORIENTATION == SCREEN_PORTRAIT | 585 | #if CONFIG_ORIENTATION == SCREEN_PORTRAIT |
343 | char *dst=(char *)FRAME+x+y*(LCD_NATIVE_WIDTH+LCD_FUDGE); | 586 | #if defined(PORTRAIT_USE_DMA) |
344 | 587 | src = src+src_x+src_y*LCD_WIDTH; | |
345 | src = src+src_x+src_y*LCD_WIDTH; | 588 | char *dst=(char *)FRAME+x+y*(LCD_NATIVE_WIDTH+LCD_FUDGE); |
346 | while(height--) | 589 | |
347 | { | 590 | dma_start_transfer16( (char *)src, (char *)dst, LCD_WIDTH>>1, |
348 | memcpy(dst, src, width); | 591 | width, height, 1); |
349 | 592 | #else | |
350 | dst = dst + ((LCD_WIDTH -x +LCD_FUDGE)); | 593 | char *dst=(char *)FRAME+x+y*(LCD_NATIVE_WIDTH+LCD_FUDGE); |
351 | src = src + (LCD_WIDTH - x); | 594 | |
352 | } | 595 | src = src+src_x+src_y*LCD_WIDTH; |
353 | 596 | while(height--) | |
597 | { | ||
598 | memcpy(dst, src, width); | ||
599 | |||
600 | dst = dst + ((LCD_WIDTH -x +LCD_FUDGE)); | ||
601 | src = src + (LCD_WIDTH - x); | ||
602 | } | ||
603 | #endif | ||
354 | #else | 604 | #else |
355 | char *dst=(char *)FRAME | 605 | char *dst=(char *)FRAME |
356 | + (LCD_NATIVE_WIDTH+LCD_FUDGE)*(LCD_NATIVE_HEIGHT-1) | 606 | + (LCD_NATIVE_WIDTH+LCD_FUDGE)*(LCD_NATIVE_HEIGHT-1) |