diff options
Diffstat (limited to 'drivers/video/sis/sis_accel.c')
-rw-r--r-- | drivers/video/sis/sis_accel.c | 479 |
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 */ |