patch-2.4.21 linux-2.4.21/drivers/video/sis/sis_accel.c

Next file: linux-2.4.21/drivers/video/sis/sis_accel.h
Previous file: linux-2.4.21/drivers/video/sis/osdef.h
Back to the patch index
Back to the overall index

diff -urN linux-2.4.20/drivers/video/sis/sis_accel.c linux-2.4.21/drivers/video/sis/sis_accel.c
@@ -37,13 +37,21 @@
 #include <linux/agp_backend.h>
 
 #include <linux/types.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 #include <linux/sisfb.h>
+#else
+#include <video/sisfb.h>
+#endif
 
 #include <asm/io.h>
+
+#ifdef CONFIG_MTRR
 #include <asm/mtrr.h>
+#endif
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 #include <video/fbcon.h>
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33)
 #include <video/fbcon-cfb8.h>
 #include <video/fbcon-cfb16.h>
 #include <video/fbcon-cfb24.h>
@@ -58,6 +66,7 @@
 
 extern struct     video_info ivideo;
 extern VGA_ENGINE sisvga_engine;
+extern int sisfb_accel;
 
 static const int sisALUConv[] =
 {
@@ -229,15 +238,38 @@
                                 int width, int height)
 {
 	long srcbase, dstbase;
+	int mymin, mymax;
 
 	srcbase = dstbase = 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;
+	mymin = min(src_y, dst_y);
+	mymax = max(src_y, dst_y);
+	
+	/* Although the chip knows the direction to use
+	 * 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 
+	 * if the coordinates exceed the valid range.
+	 * 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;
+	   }
+	} 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;
+	   }
 	}
 
 	SiS310SetupSRCBase(srcbase);
@@ -287,31 +319,64 @@
     return(0);
 }
 
+void sisfb_syncaccel(void)
+{
+    if(sisvga_engine == SIS_300_VGA) {
+    	SiS300Sync();
+    } else {
+    	SiS310Sync();
+    }
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)  /* --------------- 2.5 --------------- */
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34)  /* --- KERNEL 2.5.34 and later --- */
+int fbcon_sis_sync(struct fb_info *info)
+{
+   if(!ivideo.accel)
+   	return 0;
+   
+   CRITFLAGS
+   if(sisvga_engine == SIS_300_VGA) {
+      SiS300Sync();
+   } else {
+      SiS310Sync();
+   }
+   CRITEND
+   return 0;
+}
 
-void fbcon_sis_fillrect(struct fb_info *info, struct fb_fillrect *rect)
+void fbcon_sis_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 {
+   int col=0;
    CRITFLAGS
 
    TWDEBUG("Inside sis_fillrect");
    if(!rect->width || !rect->height)
    	return;
 
-   if(!sisfb_accel) {
-        cfb_fillrect(info, rect);
+   if(!ivideo.accel) {
+	cfb_fillrect(info, rect);
 	return;
    }
+   
+   switch(info->var.bits_per_pixel) {
+		case 8: col = rect->color;
+			break;
+		case 16: col = ((u32 *)(info->pseudo_palette))[rect->color];
+			 break;
+		case 32: col = ((u32 *)(info->pseudo_palette))[rect->color];
+			 break;
+	}	
 
    if(sisvga_engine == SIS_300_VGA) {
 	   CRITBEGIN
-	   SiS300SetupForSolidFill(rect->color, myrops[rect->rop], 0);
+	   SiS300SetupForSolidFill(col, myrops[rect->rop], 0);
 	   SiS300SubsequentSolidFillRect(rect->dx, rect->dy, rect->width, rect->height);
 	   CRITEND
 	   SiS300Sync();
    } else {
 	   CRITBEGIN
-	   SiS310SetupForSolidFill(rect->color, myrops[rect->rop], 0);
+	   SiS310SetupForSolidFill(col, myrops[rect->rop], 0);
 	   SiS310SubsequentSolidFillRect(rect->dx, rect->dy, rect->width, rect->height);
 	   CRITEND
 	   SiS310Sync();
@@ -319,13 +384,13 @@
 
 }
 
-void fbcon_sis_copyarea(struct fb_info *info, struct fb_copyarea *area)
+void fbcon_sis_copyarea(struct fb_info *info, const struct fb_copyarea *area)
 {
    int xdir, ydir;
    CRITFLAGS
 
    TWDEBUG("Inside sis_copyarea");
-   if(!sisfb_accel) {
+   if(!ivideo.accel) {
    	cfb_copyarea(info, area);
 	return;
    }
@@ -355,7 +420,7 @@
 
 #endif
 
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33)  /* ------ KERNEL <2.5.34 ------ */
+#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)
@@ -363,6 +428,27 @@
         int xdir, ydir;
 	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);
@@ -370,7 +456,6 @@
 	width *= fontwidth(p);
 	height *= fontheight(p);
 
-
 	if(srcx < dstx) xdir = 0;
 	else            xdir = 1;
 	if(srcy < dsty) ydir = 0;
@@ -388,6 +473,10 @@
 	   SiS310SubsequentScreenToScreenCopy(srcx, srcy, dstx, dsty, width, height);
 	   CRITEND
 	   SiS310Sync();
+#if 0	   
+	   printk(KERN_INFO "sis_bmove sx %d sy %d dx %d dy %d w %d h %d\n",
+		srcx, srcy, dstx, dsty, width, height);
+#endif		
 	}
 }
 
@@ -422,6 +511,13 @@
 {
 	u32 bgx;
 
+	if(!ivideo.accel) {
+#ifdef FBCON_HAS_CFB8
+	    fbcon_cfb8_clear(conp, p, srcy, srcx, height, width);
+#endif
+	    return;
+	}
+
 	bgx = attr_bgcol_ec(p, conp);
 	fbcon_sis_clear(conp, p, srcy, srcx, height, width, bgx);
 }
@@ -430,6 +526,12 @@
 			int srcy, int srcx, int height, int width)
 {
 	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);
@@ -440,6 +542,13 @@
 {
 	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);
 }
@@ -448,6 +557,22 @@
 {
 	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);
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)