diff options
author | Krzysztof Helt <krzysztof.h1@wp.pl> | 2009-03-31 18:25:11 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-01 11:59:28 -0400 |
commit | 8343c89c4f1aac4fced7bb6919b0bdd0c13edcdc (patch) | |
tree | 7ab000f00e0a12706b110091dc5f16a5cfd340bb /drivers/video | |
parent | 78d780e07247d52d3943b019bf9459bc9e95de1e (diff) |
cirrusfb: acceleration improvements
- Fix color expansion for 16bpp and 32bpp modes in the
cirrusfb_RectFill().
- Make a function with a common blitter code (cirrusfb_set_blitter).
- Add fb_sync function to allow a higher layer synchronize with the
blitter.
- Kill one redundant blitter reset.
Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/cirrusfb.c | 186 |
1 files changed, 75 insertions, 111 deletions
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index cac4e2b0cbae..e4ac2f6d4d97 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c | |||
@@ -381,7 +381,7 @@ static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel, | |||
381 | static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel, | 381 | static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel, |
382 | u_short x, u_short y, | 382 | u_short x, u_short y, |
383 | u_short width, u_short height, | 383 | u_short width, u_short height, |
384 | u_char color, u_short line_length); | 384 | u32 color, u_short line_length); |
385 | 385 | ||
386 | static void bestclock(long freq, int *nom, int *den, int *div); | 386 | static void bestclock(long freq, int *nom, int *den, int *div); |
387 | 387 | ||
@@ -1550,9 +1550,6 @@ static void init_vgachip(struct fb_info *info) | |||
1550 | /* unlock all extension registers */ | 1550 | /* unlock all extension registers */ |
1551 | vga_wseq(cinfo->regbase, CL_SEQR6, 0x12); | 1551 | vga_wseq(cinfo->regbase, CL_SEQR6, 0x12); |
1552 | 1552 | ||
1553 | /* reset blitter */ | ||
1554 | vga_wgfx(cinfo->regbase, CL_GR31, 0x04); | ||
1555 | |||
1556 | switch (cinfo->btype) { | 1553 | switch (cinfo->btype) { |
1557 | case BT_GD5480: | 1554 | case BT_GD5480: |
1558 | vga_wseq(cinfo->regbase, CL_SEQRF, 0x98); | 1555 | vga_wseq(cinfo->regbase, CL_SEQRF, 0x98); |
@@ -1747,6 +1744,17 @@ static void switch_monitor(struct cirrusfb_info *cinfo, int on) | |||
1747 | /* Linux 2.6-style accelerated functions */ | 1744 | /* Linux 2.6-style accelerated functions */ |
1748 | /******************************************/ | 1745 | /******************************************/ |
1749 | 1746 | ||
1747 | static int cirrusfb_sync(struct fb_info *info) | ||
1748 | { | ||
1749 | struct cirrusfb_info *cinfo = info->par; | ||
1750 | |||
1751 | if (!is_laguna(cinfo)) { | ||
1752 | while (vga_rgfx(cinfo->regbase, CL_GR31) & 0x03) | ||
1753 | cpu_relax(); | ||
1754 | } | ||
1755 | return 0; | ||
1756 | } | ||
1757 | |||
1750 | static void cirrusfb_fillrect(struct fb_info *info, | 1758 | static void cirrusfb_fillrect(struct fb_info *info, |
1751 | const struct fb_fillrect *region) | 1759 | const struct fb_fillrect *region) |
1752 | { | 1760 | { |
@@ -1966,6 +1974,7 @@ static struct fb_ops cirrusfb_ops = { | |||
1966 | .fb_blank = cirrusfb_blank, | 1974 | .fb_blank = cirrusfb_blank, |
1967 | .fb_fillrect = cirrusfb_fillrect, | 1975 | .fb_fillrect = cirrusfb_fillrect, |
1968 | .fb_copyarea = cirrusfb_copyarea, | 1976 | .fb_copyarea = cirrusfb_copyarea, |
1977 | .fb_sync = cirrusfb_sync, | ||
1969 | .fb_imageblit = cirrusfb_imageblit, | 1978 | .fb_imageblit = cirrusfb_imageblit, |
1970 | }; | 1979 | }; |
1971 | 1980 | ||
@@ -2586,7 +2595,6 @@ static void RClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned ch | |||
2586 | /* FIXME: use interrupts instead */ | 2595 | /* FIXME: use interrupts instead */ |
2587 | static void cirrusfb_WaitBLT(u8 __iomem *regbase) | 2596 | static void cirrusfb_WaitBLT(u8 __iomem *regbase) |
2588 | { | 2597 | { |
2589 | /* now busy-wait until we're done */ | ||
2590 | while (vga_rgfx(regbase, CL_GR31) & 0x08) | 2598 | while (vga_rgfx(regbase, CL_GR31) & 0x08) |
2591 | cpu_relax(); | 2599 | cpu_relax(); |
2592 | } | 2600 | } |
@@ -2597,58 +2605,12 @@ static void cirrusfb_WaitBLT(u8 __iomem *regbase) | |||
2597 | perform accelerated "scrolling" | 2605 | perform accelerated "scrolling" |
2598 | ********************************************************************/ | 2606 | ********************************************************************/ |
2599 | 2607 | ||
2600 | static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel, | 2608 | static void cirrusfb_set_blitter(u8 __iomem *regbase, |
2601 | u_short curx, u_short cury, | 2609 | u_short nwidth, u_short nheight, |
2602 | u_short destx, u_short desty, | 2610 | u_long nsrc, u_long ndest, |
2603 | u_short width, u_short height, | 2611 | u_short bltmode, u_short line_length) |
2604 | u_short line_length) | ||
2605 | { | ||
2606 | u_short nwidth, nheight; | ||
2607 | u_long nsrc, ndest; | ||
2608 | u_char bltmode; | ||
2609 | |||
2610 | nwidth = width - 1; | ||
2611 | nheight = height - 1; | ||
2612 | |||
2613 | bltmode = 0x00; | ||
2614 | /* if source adr < dest addr, do the Blt backwards */ | ||
2615 | if (cury <= desty) { | ||
2616 | if (cury == desty) { | ||
2617 | /* if src and dest are on the same line, check x */ | ||
2618 | if (curx < destx) | ||
2619 | bltmode |= 0x01; | ||
2620 | } else | ||
2621 | bltmode |= 0x01; | ||
2622 | } | ||
2623 | if (!bltmode) { | ||
2624 | /* standard case: forward blitting */ | ||
2625 | nsrc = (cury * line_length) + curx; | ||
2626 | ndest = (desty * line_length) + destx; | ||
2627 | } else { | ||
2628 | /* this means start addresses are at the end, | ||
2629 | * counting backwards | ||
2630 | */ | ||
2631 | nsrc = cury * line_length + curx + | ||
2632 | nheight * line_length + nwidth; | ||
2633 | ndest = desty * line_length + destx + | ||
2634 | nheight * line_length + nwidth; | ||
2635 | } | ||
2636 | |||
2637 | /* | ||
2638 | run-down of registers to be programmed: | ||
2639 | destination pitch | ||
2640 | source pitch | ||
2641 | BLT width/height | ||
2642 | source start | ||
2643 | destination start | ||
2644 | BLT mode | ||
2645 | BLT ROP | ||
2646 | VGA_GFX_SR_VALUE / VGA_GFX_SR_ENABLE: "fill color" | ||
2647 | start/stop | ||
2648 | */ | ||
2649 | |||
2650 | cirrusfb_WaitBLT(regbase); | ||
2651 | 2612 | ||
2613 | { | ||
2652 | /* pitch: set to line_length */ | 2614 | /* pitch: set to line_length */ |
2653 | /* dest pitch low */ | 2615 | /* dest pitch low */ |
2654 | vga_wgfx(regbase, CL_GR24, line_length & 0xff); | 2616 | vga_wgfx(regbase, CL_GR24, line_length & 0xff); |
@@ -2694,56 +2656,67 @@ static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel, | |||
2694 | vga_wgfx(regbase, CL_GR32, 0x0d); /* BLT ROP */ | 2656 | vga_wgfx(regbase, CL_GR32, 0x0d); /* BLT ROP */ |
2695 | 2657 | ||
2696 | /* and finally: GO! */ | 2658 | /* and finally: GO! */ |
2697 | vga_wgfx(regbase, CL_GR31, 0x02); /* BLT Start/status */ | 2659 | vga_wgfx(regbase, CL_GR31, 0x82); /* BLT Start/status */ |
2698 | } | 2660 | } |
2699 | 2661 | ||
2700 | /******************************************************************* | 2662 | /******************************************************************* |
2701 | cirrusfb_RectFill() | 2663 | cirrusfb_BitBLT() |
2702 | 2664 | ||
2703 | perform accelerated rectangle fill | 2665 | perform accelerated "scrolling" |
2704 | ********************************************************************/ | 2666 | ********************************************************************/ |
2705 | 2667 | ||
2706 | static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel, | 2668 | static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel, |
2707 | u_short x, u_short y, u_short width, u_short height, | 2669 | u_short curx, u_short cury, |
2708 | u_char color, u_short line_length) | 2670 | u_short destx, u_short desty, |
2671 | u_short width, u_short height, | ||
2672 | u_short line_length) | ||
2709 | { | 2673 | { |
2710 | u_short nwidth, nheight; | 2674 | u_short nwidth = width - 1; |
2711 | u_long ndest; | 2675 | u_short nheight = height - 1; |
2712 | u_char op; | 2676 | u_long nsrc, ndest; |
2713 | 2677 | u_char bltmode; | |
2714 | nwidth = width - 1; | ||
2715 | nheight = height - 1; | ||
2716 | 2678 | ||
2717 | ndest = (y * line_length) + x; | 2679 | bltmode = 0x00; |
2680 | /* if source adr < dest addr, do the Blt backwards */ | ||
2681 | if (cury <= desty) { | ||
2682 | if (cury == desty) { | ||
2683 | /* if src and dest are on the same line, check x */ | ||
2684 | if (curx < destx) | ||
2685 | bltmode |= 0x01; | ||
2686 | } else | ||
2687 | bltmode |= 0x01; | ||
2688 | } | ||
2689 | /* standard case: forward blitting */ | ||
2690 | nsrc = (cury * line_length) + curx; | ||
2691 | ndest = (desty * line_length) + destx; | ||
2692 | if (bltmode) { | ||
2693 | /* this means start addresses are at the end, | ||
2694 | * counting backwards | ||
2695 | */ | ||
2696 | nsrc += nheight * line_length + nwidth; | ||
2697 | ndest += nheight * line_length + nwidth; | ||
2698 | } | ||
2718 | 2699 | ||
2719 | cirrusfb_WaitBLT(regbase); | 2700 | cirrusfb_WaitBLT(regbase); |
2720 | 2701 | ||
2721 | /* pitch: set to line_length */ | 2702 | cirrusfb_set_blitter(regbase, nwidth, nheight, |
2722 | vga_wgfx(regbase, CL_GR24, line_length & 0xff); /* dest pitch low */ | 2703 | nsrc, ndest, bltmode, line_length); |
2723 | vga_wgfx(regbase, CL_GR25, line_length >> 8); /* dest pitch hi */ | 2704 | } |
2724 | vga_wgfx(regbase, CL_GR26, line_length & 0xff); /* source pitch low */ | ||
2725 | vga_wgfx(regbase, CL_GR27, line_length >> 8); /* source pitch hi */ | ||
2726 | 2705 | ||
2727 | /* BLT width: actual number of pixels - 1 */ | 2706 | /******************************************************************* |
2728 | vga_wgfx(regbase, CL_GR20, nwidth & 0xff); /* BLT width low */ | 2707 | cirrusfb_RectFill() |
2729 | vga_wgfx(regbase, CL_GR21, nwidth >> 8); /* BLT width hi */ | ||
2730 | 2708 | ||
2731 | /* BLT height: actual number of lines -1 */ | 2709 | perform accelerated rectangle fill |
2732 | vga_wgfx(regbase, CL_GR22, nheight & 0xff); /* BLT height low */ | 2710 | ********************************************************************/ |
2733 | vga_wgfx(regbase, CL_GR23, nheight >> 8); /* BLT width hi */ | ||
2734 | 2711 | ||
2735 | /* BLT destination */ | 2712 | static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel, |
2736 | /* BLT dest low */ | 2713 | u_short x, u_short y, u_short width, u_short height, |
2737 | vga_wgfx(regbase, CL_GR28, (u_char) (ndest & 0xff)); | 2714 | u32 color, u_short line_length) |
2738 | /* BLT dest mid */ | 2715 | { |
2739 | vga_wgfx(regbase, CL_GR29, (u_char) (ndest >> 8)); | 2716 | u_long ndest = (y * line_length) + x; |
2740 | /* BLT dest hi */ | 2717 | u_char op; |
2741 | vga_wgfx(regbase, CL_GR2A, (u_char) (ndest >> 16)); | ||
2742 | 2718 | ||
2743 | /* BLT source: set to 0 (is a dummy here anyway) */ | 2719 | cirrusfb_WaitBLT(regbase); |
2744 | vga_wgfx(regbase, CL_GR2C, 0x00); /* BLT src low */ | ||
2745 | vga_wgfx(regbase, CL_GR2D, 0x00); /* BLT src mid */ | ||
2746 | vga_wgfx(regbase, CL_GR2E, 0x00); /* BLT src hi */ | ||
2747 | 2720 | ||
2748 | /* This is a ColorExpand Blt, using the */ | 2721 | /* This is a ColorExpand Blt, using the */ |
2749 | /* same color for foreground and background */ | 2722 | /* same color for foreground and background */ |
@@ -2751,29 +2724,20 @@ static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel, | |||
2751 | vga_wgfx(regbase, VGA_GFX_SR_ENABLE, color); /* background color */ | 2724 | vga_wgfx(regbase, VGA_GFX_SR_ENABLE, color); /* background color */ |
2752 | 2725 | ||
2753 | op = 0xc0; | 2726 | op = 0xc0; |
2754 | if (bits_per_pixel == 16) { | 2727 | if (bits_per_pixel >= 16) { |
2755 | vga_wgfx(regbase, CL_GR10, color); /* foreground color */ | 2728 | vga_wgfx(regbase, CL_GR10, color >> 8); /* foreground color */ |
2756 | vga_wgfx(regbase, CL_GR11, color); /* background color */ | 2729 | vga_wgfx(regbase, CL_GR11, color >> 8); /* background color */ |
2757 | op = 0x50; | ||
2758 | op = 0xd0; | 2730 | op = 0xd0; |
2759 | } else if (bits_per_pixel == 32) { | 2731 | } |
2760 | vga_wgfx(regbase, CL_GR10, color); /* foreground color */ | 2732 | if (bits_per_pixel == 32) { |
2761 | vga_wgfx(regbase, CL_GR11, color); /* background color */ | 2733 | vga_wgfx(regbase, CL_GR12, color >> 16);/* foreground color */ |
2762 | vga_wgfx(regbase, CL_GR12, color); /* foreground color */ | 2734 | vga_wgfx(regbase, CL_GR13, color >> 16);/* background color */ |
2763 | vga_wgfx(regbase, CL_GR13, color); /* background color */ | 2735 | vga_wgfx(regbase, CL_GR14, color >> 24);/* foreground color */ |
2764 | vga_wgfx(regbase, CL_GR14, 0); /* foreground color */ | 2736 | vga_wgfx(regbase, CL_GR15, color >> 24);/* background color */ |
2765 | vga_wgfx(regbase, CL_GR15, 0); /* background color */ | ||
2766 | op = 0x50; | ||
2767 | op = 0xf0; | 2737 | op = 0xf0; |
2768 | } | 2738 | } |
2769 | /* BLT mode: color expand, Enable 8x8 copy (faster?) */ | 2739 | cirrusfb_set_blitter(regbase, width - 1, height - 1, |
2770 | vga_wgfx(regbase, CL_GR30, op); /* BLT mode */ | 2740 | 0, ndest, op, line_length); |
2771 | |||
2772 | /* BLT ROP: SrcCopy */ | ||
2773 | vga_wgfx(regbase, CL_GR32, 0x0d); /* BLT ROP */ | ||
2774 | |||
2775 | /* and finally: GO! */ | ||
2776 | vga_wgfx(regbase, CL_GR31, 0x02); /* BLT Start/status */ | ||
2777 | } | 2741 | } |
2778 | 2742 | ||
2779 | /************************************************************************** | 2743 | /************************************************************************** |