aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorKrzysztof Helt <krzysztof.h1@wp.pl>2009-03-31 18:25:11 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-01 11:59:28 -0400
commit8343c89c4f1aac4fced7bb6919b0bdd0c13edcdc (patch)
tree7ab000f00e0a12706b110091dc5f16a5cfd340bb /drivers
parent78d780e07247d52d3943b019bf9459bc9e95de1e (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')
-rw-r--r--drivers/video/cirrusfb.c186
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,
381static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel, 381static 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
386static void bestclock(long freq, int *nom, int *den, int *div); 386static 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
1747static 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
1750static void cirrusfb_fillrect(struct fb_info *info, 1758static 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 */
2587static void cirrusfb_WaitBLT(u8 __iomem *regbase) 2596static 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
2600static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel, 2608static 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
2706static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel, 2668static 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 */ 2712static 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/**************************************************************************