aboutsummaryrefslogtreecommitdiff
path: root/drivers/video/sis/sis_accel.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/sis/sis_accel.c')
-rw-r--r--drivers/video/sis/sis_accel.c479
1 files changed, 126 insertions, 353 deletions
diff --git a/drivers/video/sis/sis_accel.c b/drivers/video/sis/sis_accel.c
index 30e90a553e8..bab933e6c6a 100644
--- a/drivers/video/sis/sis_accel.c
+++ b/drivers/video/sis/sis_accel.c
@@ -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/
@@ -30,13 +32,11 @@
#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 */