Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / video / sis / sis_accel.c
index 30e90a5..bab933e 100644 (file)
@@ -1,6 +1,8 @@
 /*
- * SiS 300/630/730/540/315/550/65x/74x/330/760 frame buffer driver
- * for Linux kernels 2.4.x and 2.6.x
+ * SiS 300/540/630[S]/730[S],
+ * SiS 315[E|PRO]/550/[M]650/651/[M]661[F|M]X/740/[M]741[GX]/330/[M]760[GX],
+ * XGI V3XT/V5/V8, Z7
+ * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
  *
  * 2D acceleration part
  *
@@ -19,7 +21,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
  *
  * Based on the XFree86/X.org driver which is
- *     Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ *     Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
  *
  * Author: Thomas Winischhofer <thomas@winischhofer.net>
  *                     (see http://www.winischhofer.net/
 #include <linux/version.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/errno.h>
 #include <linux/fb.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 #include <linux/console.h>
-#include <linux/selection.h>
+#endif
 #include <linux/ioport.h>
-#include <linux/capability.h>
-#include <linux/fs.h>
 #include <linux/types.h>
 
 #include <asm/io.h>
@@ -188,7 +188,7 @@ SiS300SubsequentSolidFillRect(struct sis_video_info *ivideo, int x, int y, int w
 }
 #endif
 
-/* 315/330 series ------------------------------------------------- */
+/* 315/330/340 series ---------------------------------------------- */
 
 #ifdef CONFIG_FB_SIS_315
 static void
@@ -202,7 +202,7 @@ SiS310SetupForScreenToScreenCopy(struct sis_video_info *ivideo, int rop, int tra
 {
        SiS310SetupDSTColorDepth(ivideo->DstColor);
        SiS310SetupSRCPitch(ivideo->video_linelength)
-       SiS310SetupDSTRect(ivideo->video_linelength, 0xffff)
+       SiS310SetupDSTRect(ivideo->video_linelength, 0x0fff)
        if(trans_color != -1) {
                SiS310SetupROP(0x0A)
                SiS310SetupSRCTrans(trans_color)
@@ -213,7 +213,7 @@ SiS310SetupForScreenToScreenCopy(struct sis_video_info *ivideo, int rop, int tra
                /* SiSSetupCMDFlag(BITBLT | SRCVIDEO) */
        }
        SiS310SetupCMDFlag(ivideo->SiS310_AccelDepth)
-       /* The 315 series is smart enough to know the direction */
+       /* The chip is smart enough to know the direction */
 }
 
 static void
@@ -223,35 +223,38 @@ SiS310SubsequentScreenToScreenCopy(struct sis_video_info *ivideo, int src_x, int
        u32 srcbase = 0, dstbase = 0;
        int mymin = min(src_y, dst_y);
        int mymax = max(src_y, dst_y);
-       
+
        /* Although the chip knows the direction to use
-        * if the source and destination areas overlap, 
+        * if the source and destination areas overlap,
         * that logic fails if we fiddle with the bitmap
         * addresses. Therefore, we check if the source
-        * and destination blitting areas overlap and 
-        * adapt the bitmap addresses synchronously 
+        * and destination blitting areas overlap and
+        * adapt the bitmap addresses synchronously
         * if the coordinates exceed the valid range.
-        * The the areas do not overlap, we do our 
+        * The the areas do not overlap, we do our
         * normal check.
         */
-       if((mymax - mymin) < height) { 
-          if((src_y >= 2048) || (dst_y >= 2048)) {           
-             srcbase = ivideo->video_linelength * mymin;
-             dstbase = ivideo->video_linelength * mymin;
-             src_y -= mymin;
-             dst_y -= mymin;
-          }
+       if((mymax - mymin) < height) {
+               if((src_y >= 2048) || (dst_y >= 2048)) {
+                       srcbase = ivideo->video_linelength * mymin;
+                       dstbase = ivideo->video_linelength * mymin;
+                       src_y -= mymin;
+                       dst_y -= mymin;
+               }
        } else {
-          if(src_y >= 2048) {
-             srcbase = ivideo->video_linelength * src_y;
-             src_y = 0;
-          }
-          if(dst_y >= 2048) {
-             dstbase = ivideo->video_linelength * dst_y;
-             dst_y = 0;
-          }
+               if(src_y >= 2048) {
+                       srcbase = ivideo->video_linelength * src_y;
+                       src_y = 0;
+               }
+               if(dst_y >= 2048) {
+                       dstbase = ivideo->video_linelength * dst_y;
+                       dst_y = 0;
+               }
        }
 
+       srcbase += ivideo->video_offset;
+       dstbase += ivideo->video_offset;
+
        SiS310SetupSRCBase(srcbase);
        SiS310SetupDSTBase(dstbase);
        SiS310SetupRect(width, height)
@@ -264,7 +267,7 @@ static void
 SiS310SetupForSolidFill(struct sis_video_info *ivideo, u32 color, int rop)
 {
        SiS310SetupPATFG(color)
-       SiS310SetupDSTRect(ivideo->video_linelength, 0xffff)
+       SiS310SetupDSTRect(ivideo->video_linelength, 0x0fff)
        SiS310SetupDSTColorDepth(ivideo->DstColor);
        SiS310SetupROP(sisPatALUConv[rop])
        SiS310SetupCMDFlag(PATFG | ivideo->SiS310_AccelDepth)
@@ -279,6 +282,7 @@ SiS310SubsequentSolidFillRect(struct sis_video_info *ivideo, int x, int y, int w
                dstbase = ivideo->video_linelength * y;
                y = 0;
        }
+       dstbase += ivideo->video_offset;
        SiS310SetupDSTBase(dstbase)
        SiS310SetupDSTXY(x,y)
        SiS310SetupRect(w,h)
@@ -294,384 +298,153 @@ SiS310SubsequentSolidFillRect(struct sis_video_info *ivideo, int x, int y, int w
 int sisfb_initaccel(struct sis_video_info *ivideo)
 {
 #ifdef SISFB_USE_SPINLOCKS
-    spin_lock_init(&ivideo->lockaccel);
+       spin_lock_init(&ivideo->lockaccel);
 #endif
-    return(0);
+       return 0;
 }
 
 void sisfb_syncaccel(struct sis_video_info *ivideo)
 {
-    if(ivideo->sisvga_engine == SIS_300_VGA) {
+       if(ivideo->sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
-       SiS300Sync(ivideo);
+               SiS300Sync(ivideo);
 #endif
-    } else {
+       } else {
 #ifdef CONFIG_FB_SIS_315
-       SiS310Sync(ivideo);
+               SiS310Sync(ivideo);
 #endif
-    }
+       }
 }
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)  /* --------------- 2.5 --------------- */
 
 int fbcon_sis_sync(struct fb_info *info)
 {
-   struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-   CRITFLAGS
+       struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+       CRITFLAGS
 
-   if(!ivideo->accel)
-       return 0;
+       if((!ivideo->accel) || (!ivideo->engineok))
+               return 0;
 
-   if(ivideo->sisvga_engine == SIS_300_VGA) {
-#ifdef CONFIG_FB_SIS_300
-      SiS300Sync(ivideo);
-#endif
-   } else {
-#ifdef CONFIG_FB_SIS_315
-      SiS310Sync(ivideo);
-#endif
-   }
-   CRITEND
-   return 0;
+       CRITBEGIN
+       sisfb_syncaccel(ivideo);
+       CRITEND
+
+       return 0;
 }
 
 void fbcon_sis_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 {
-   struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-   u32 col = 0;
-   u32 vxres = info->var.xres_virtual;
-   u32 vyres = info->var.yres_virtual;
-   int width, height;
-   CRITFLAGS
-
-   if(info->state != FBINFO_STATE_RUNNING) {
-       return;
-   }
-
-   if(!ivideo->accel) {
-       cfb_fillrect(info, rect);
-       return;
-   }
-   
-   if(!rect->width || !rect->height || rect->dx >= vxres || rect->dy >= vyres) {
-       return;
-   }
-
-   /* Clipping */
-   width = ((rect->dx + rect->width) > vxres) ? (vxres - rect->dx) : rect->width;
-   height = ((rect->dy + rect->height) > vyres) ? (vyres - rect->dy) : rect->height;
-
-   switch(info->var.bits_per_pixel) {
+       struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+       u32 col = 0;
+       u32 vxres = info->var.xres_virtual;
+       u32 vyres = info->var.yres_virtual;
+       int width, height;
+       CRITFLAGS
+
+       if(info->state != FBINFO_STATE_RUNNING)
+               return;
+
+       if((!ivideo->accel) || (!ivideo->engineok)) {
+               cfb_fillrect(info, rect);
+               return;
+       }
+
+       if(!rect->width || !rect->height || rect->dx >= vxres || rect->dy >= vyres)
+               return;
+
+       /* Clipping */
+       width = ((rect->dx + rect->width) > vxres) ? (vxres - rect->dx) : rect->width;
+       height = ((rect->dy + rect->height) > vyres) ? (vyres - rect->dy) : rect->height;
+
+       switch(info->var.bits_per_pixel) {
        case 8:  col = rect->color;
                 break;
        case 16:
        case 32: col = ((u32 *)(info->pseudo_palette))[rect->color];
                 break;
-   }
+       }
 
-   if(ivideo->sisvga_engine == SIS_300_VGA) {
+       if(ivideo->sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
-      CRITBEGIN
-      SiS300SetupForSolidFill(ivideo, col, myrops[rect->rop]);
-      SiS300SubsequentSolidFillRect(ivideo, rect->dx, rect->dy, width, height);
-      CRITEND
-      SiS300Sync(ivideo);
+               CRITBEGIN
+               SiS300SetupForSolidFill(ivideo, col, myrops[rect->rop]);
+               SiS300SubsequentSolidFillRect(ivideo, rect->dx, rect->dy, width, height);
+               CRITEND
 #endif
-   } else {
+       } else {
 #ifdef CONFIG_FB_SIS_315
-      CRITBEGIN
-      SiS310SetupForSolidFill(ivideo, col, myrops[rect->rop]);
-      SiS310SubsequentSolidFillRect(ivideo, rect->dx, rect->dy, width, height);
-      CRITEND
-      SiS310Sync(ivideo);
+               CRITBEGIN
+               SiS310SetupForSolidFill(ivideo, col, myrops[rect->rop]);
+               SiS310SubsequentSolidFillRect(ivideo, rect->dx, rect->dy, width, height);
+               CRITEND
 #endif
-   }
+       }
 
+       sisfb_syncaccel(ivideo);
 }
 
 void fbcon_sis_copyarea(struct fb_info *info, const struct fb_copyarea *area)
 {
-   struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-   u32 vxres = info->var.xres_virtual;
-   u32 vyres = info->var.yres_virtual;
-   int width = area->width;
-   int height = area->height;
-   CRITFLAGS
-
-   if(info->state != FBINFO_STATE_RUNNING) {
-       return;
-   }
-
-   if(!ivideo->accel) {
-       cfb_copyarea(info, area);
-       return;
-   }
-
-   if(!width || !height ||
-      area->sx >= vxres || area->sy >= vyres ||
-      area->dx >= vxres || area->dy >= vyres) {
-       return;
-   }
-
-   /* Clipping */
-   if((area->sx + width) > vxres) width = vxres - area->sx;
-   if((area->dx + width) > vxres) width = vxres - area->dx;
-   if((area->sy + height) > vyres) height = vyres - area->sy;
-   if((area->dy + height) > vyres) height = vyres - area->dy;
-
-   if(ivideo->sisvga_engine == SIS_300_VGA) {
-#ifdef CONFIG_FB_SIS_300
-      int xdir, ydir;
-
-      if(area->sx < area->dx) xdir = 0;
-      else                    xdir = 1;
-      if(area->sy < area->dy) ydir = 0;
-      else                    ydir = 1;
-
-      CRITBEGIN
-      SiS300SetupForScreenToScreenCopy(ivideo, xdir, ydir, 3, -1);
-      SiS300SubsequentScreenToScreenCopy(ivideo, area->sx, area->sy, area->dx, area->dy,
-                                        width, height);
-      CRITEND
-      SiS300Sync(ivideo);
-#endif
-   } else {
-#ifdef CONFIG_FB_SIS_315
-      CRITBEGIN
-      SiS310SetupForScreenToScreenCopy(ivideo, 3, -1);
-      SiS310SubsequentScreenToScreenCopy(ivideo, area->sx, area->sy, area->dx, area->dy,
-                                        width, height);
-      CRITEND
-      SiS310Sync(ivideo);
-#endif
-   }
-}
-
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)  /* -------------- 2.4 --------------- */
-
-void fbcon_sis_bmove(struct display *p, int srcy, int srcx,
-                           int dsty, int dstx, int height, int width)
-{
-       struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
-
+       struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+       u32 vxres = info->var.xres_virtual;
+       u32 vyres = info->var.yres_virtual;
+       int width = area->width;
+       int height = area->height;
        CRITFLAGS
 
-       if(!ivideo->accel) {
-           switch(ivideo->video_bpp) {
-           case 8:
-#ifdef FBCON_HAS_CFB8
-              fbcon_cfb8_bmove(p, srcy, srcx, dsty, dstx, height, width);
-#endif
-              break;
-           case 16:
-#ifdef FBCON_HAS_CFB16
-              fbcon_cfb16_bmove(p, srcy, srcx, dsty, dstx, height, width);
-#endif
-              break;
-           case 32:
-#ifdef FBCON_HAS_CFB32
-              fbcon_cfb32_bmove(p, srcy, srcx, dsty, dstx, height, width);
-#endif
-              break;
-            }
-           return;
-       }
-
-       srcx *= fontwidth(p);
-       srcy *= fontheight(p);
-       dstx *= fontwidth(p);
-       dsty *= fontheight(p);
-       width *= fontwidth(p);
-       height *= fontheight(p);
+       if(info->state != FBINFO_STATE_RUNNING)
+               return;
 
-       if(ivideo->sisvga_engine == SIS_300_VGA) {
-#ifdef CONFIG_FB_SIS_300
-          int xdir, ydir;
-
-          if(srcx < dstx) xdir = 0;
-          else            xdir = 1;
-          if(srcy < dsty) ydir = 0;
-          else            ydir = 1;
-
-          CRITBEGIN
-          SiS300SetupForScreenToScreenCopy(ivideo, xdir, ydir, 3, -1);
-          SiS300SubsequentScreenToScreenCopy(ivideo, srcx, srcy, dstx, dsty, width, height);
-          CRITEND
-          SiS300Sync(ivideo);
-#endif
-       } else {
-#ifdef CONFIG_FB_SIS_315
-          CRITBEGIN
-          SiS310SetupForScreenToScreenCopy(ivideo, 3, -1);
-          SiS310SubsequentScreenToScreenCopy(ivideo, srcx, srcy, dstx, dsty, width, height);
-          CRITEND
-          SiS310Sync(ivideo);
-#endif
+       if((!ivideo->accel) || (!ivideo->engineok)) {
+               cfb_copyarea(info, area);
+               return;
        }
-}
 
-static void fbcon_sis_clear(struct vc_data *conp, struct display *p,
-                       int srcy, int srcx, int height, int width, int color)
-{
-        struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
-       CRITFLAGS
+       if(!width || !height ||
+          area->sx >= vxres || area->sy >= vyres ||
+          area->dx >= vxres || area->dy >= vyres)
+               return;
 
-       srcx *= fontwidth(p);
-       srcy *= fontheight(p);
-       width *= fontwidth(p);
-       height *= fontheight(p);
+       /* Clipping */
+       if((area->sx + width) > vxres) width = vxres - area->sx;
+       if((area->dx + width) > vxres) width = vxres - area->dx;
+       if((area->sy + height) > vyres) height = vyres - area->sy;
+       if((area->dy + height) > vyres) height = vyres - area->dy;
 
        if(ivideo->sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
-          CRITBEGIN
-          SiS300SetupForSolidFill(ivideo, color, 3);
-          SiS300SubsequentSolidFillRect(ivideo, srcx, srcy, width, height);
-          CRITEND
-          SiS300Sync(ivideo);
+               int xdir, ydir;
+
+               if(area->sx < area->dx) xdir = 0;
+               else                    xdir = 1;
+               if(area->sy < area->dy) ydir = 0;
+               else                    ydir = 1;
+
+               CRITBEGIN
+               SiS300SetupForScreenToScreenCopy(ivideo, xdir, ydir, 3, -1);
+               SiS300SubsequentScreenToScreenCopy(ivideo, area->sx, area->sy,
+                                       area->dx, area->dy, width, height);
+               CRITEND
 #endif
        } else {
 #ifdef CONFIG_FB_SIS_315
-          CRITBEGIN
-          SiS310SetupForSolidFill(ivideo, color, 3);
-          SiS310SubsequentSolidFillRect(ivideo, srcx, srcy, width, height);
-          CRITEND
-          SiS310Sync(ivideo);
-#endif
-       }
-}
-
-void fbcon_sis_clear8(struct vc_data *conp, struct display *p,
-                       int srcy, int srcx, int height, int width)
-{
-       struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
-       u32 bgx;
-
-       if(!ivideo->accel) {
-#ifdef FBCON_HAS_CFB8
-           fbcon_cfb8_clear(conp, p, srcy, srcx, height, width);
+               CRITBEGIN
+               SiS310SetupForScreenToScreenCopy(ivideo, 3, -1);
+               SiS310SubsequentScreenToScreenCopy(ivideo, area->sx, area->sy,
+                                       area->dx, area->dy, width, height);
+               CRITEND
 #endif
-           return;
        }
 
-       bgx = attr_bgcol_ec(p, conp);
-       fbcon_sis_clear(conp, p, srcy, srcx, height, width, bgx);
+       sisfb_syncaccel(ivideo);
 }
 
-void fbcon_sis_clear16(struct vc_data *conp, struct display *p,
-                       int srcy, int srcx, int height, int width)
-{
-        struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
-       u32 bgx;
-
-       if(!ivideo->accel) {
-#ifdef FBCON_HAS_CFB16
-           fbcon_cfb16_clear(conp, p, srcy, srcx, height, width);
 #endif
-           return;
-       }
-
-       bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
-       fbcon_sis_clear(conp, p, srcy, srcx, height, width, bgx);
-}
 
-void fbcon_sis_clear32(struct vc_data *conp, struct display *p,
-                       int srcy, int srcx, int height, int width)
-{
-       struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
-       u32 bgx;
-
-       if(!ivideo->accel) {
-#ifdef FBCON_HAS_CFB32
-           fbcon_cfb32_clear(conp, p, srcy, srcx, height, width);
-#endif
-           return;
-       }
-
-       bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
-       fbcon_sis_clear(conp, p, srcy, srcx, height, width, bgx);
-}
-
-void fbcon_sis_revc(struct display *p, int srcx, int srcy)
-{
-       struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
-       CRITFLAGS
-
-       if(!ivideo->accel) {
-           switch(ivideo->video_bpp) {
-           case 16:
-#ifdef FBCON_HAS_CFB16
-              fbcon_cfb16_revc(p, srcx, srcy);
-#endif
-              break;
-           case 32:
-#ifdef FBCON_HAS_CFB32
-              fbcon_cfb32_revc(p, srcx, srcy);
-#endif
-              break;
-            }
-           return;
-       }
-
-       srcx *= fontwidth(p);
-       srcy *= fontheight(p);
-
-       if(ivideo->sisvga_engine == SIS_300_VGA) {
-#ifdef CONFIG_FB_SIS_300
-          CRITBEGIN
-          SiS300SetupForSolidFill(ivideo, 0, 0x0a);
-          SiS300SubsequentSolidFillRect(ivideo, srcx, srcy, fontwidth(p), fontheight(p));
-          CRITEND
-          SiS300Sync(ivideo);
-#endif
-       } else {
-#ifdef CONFIG_FB_SIS_315
-          CRITBEGIN
-          SiS310SetupForSolidFill(ivideo, 0, 0x0a);
-          SiS310SubsequentSolidFillRect(ivideo, srcx, srcy, fontwidth(p), fontheight(p));
-          CRITEND
-          SiS310Sync(ivideo);
-#endif
-       }
-}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)  /* -------------- 2.4 --------------- */
 
-#ifdef FBCON_HAS_CFB8
-struct display_switch fbcon_sis8 = {
-       .setup          = fbcon_cfb8_setup,
-       .bmove          = fbcon_sis_bmove,
-       .clear          = fbcon_sis_clear8,
-       .putc           = fbcon_cfb8_putc,
-       .putcs          = fbcon_cfb8_putcs,
-       .revc           = fbcon_cfb8_revc,
-       .clear_margins  = fbcon_cfb8_clear_margins,
-       .fontwidthmask  = FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
-};
-#endif
-#ifdef FBCON_HAS_CFB16
-struct display_switch fbcon_sis16 = {
-       .setup          = fbcon_cfb16_setup,
-       .bmove          = fbcon_sis_bmove,
-       .clear          = fbcon_sis_clear16,
-       .putc           = fbcon_cfb16_putc,
-       .putcs          = fbcon_cfb16_putcs,
-       .revc           = fbcon_sis_revc,
-       .clear_margins  = fbcon_cfb16_clear_margins,
-       .fontwidthmask  = FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
-};
-#endif
-#ifdef FBCON_HAS_CFB32
-struct display_switch fbcon_sis32 = {
-       .setup          = fbcon_cfb32_setup,
-       .bmove          = fbcon_sis_bmove,
-       .clear          = fbcon_sis_clear32,
-       .putc           = fbcon_cfb32_putc,
-       .putcs          = fbcon_cfb32_putcs,
-       .revc           = fbcon_sis_revc,
-       .clear_margins  = fbcon_cfb32_clear_margins,
-       .fontwidthmask  = FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
-};
-#endif
+#include "sisfb_accel_2_4.h"
 
 #endif /* KERNEL VERSION */