1*f7018c21STomi Valkeinen /* 2*f7018c21STomi Valkeinen * SiS 300/540/630[S]/730[S], 3*f7018c21STomi Valkeinen * SiS 315[E|PRO]/550/[M]650/651/[M]661[F|M]X/740/[M]741[GX]/330/[M]760[GX], 4*f7018c21STomi Valkeinen * XGI V3XT/V5/V8, Z7 5*f7018c21STomi Valkeinen * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3 6*f7018c21STomi Valkeinen * 7*f7018c21STomi Valkeinen * 2D acceleration part 8*f7018c21STomi Valkeinen * 9*f7018c21STomi Valkeinen * This program is free software; you can redistribute it and/or modify 10*f7018c21STomi Valkeinen * it under the terms of the GNU General Public License as published by 11*f7018c21STomi Valkeinen * the Free Software Foundation; either version 2 of the named License, 12*f7018c21STomi Valkeinen * or any later version. 13*f7018c21STomi Valkeinen * 14*f7018c21STomi Valkeinen * This program is distributed in the hope that it will be useful, 15*f7018c21STomi Valkeinen * but WITHOUT ANY WARRANTY; without even the implied warranty of 16*f7018c21STomi Valkeinen * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17*f7018c21STomi Valkeinen * GNU General Public License for more details. 18*f7018c21STomi Valkeinen * 19*f7018c21STomi Valkeinen * You should have received a copy of the GNU General Public License 20*f7018c21STomi Valkeinen * along with this program; if not, write to the Free Software 21*f7018c21STomi Valkeinen * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA 22*f7018c21STomi Valkeinen * 23*f7018c21STomi Valkeinen * Based on the XFree86/X.org driver which is 24*f7018c21STomi Valkeinen * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria 25*f7018c21STomi Valkeinen * 26*f7018c21STomi Valkeinen * Author: Thomas Winischhofer <thomas@winischhofer.net> 27*f7018c21STomi Valkeinen * (see http://www.winischhofer.net/ 28*f7018c21STomi Valkeinen * for more information and updates) 29*f7018c21STomi Valkeinen */ 30*f7018c21STomi Valkeinen 31*f7018c21STomi Valkeinen #include <linux/module.h> 32*f7018c21STomi Valkeinen #include <linux/kernel.h> 33*f7018c21STomi Valkeinen #include <linux/fb.h> 34*f7018c21STomi Valkeinen #include <linux/ioport.h> 35*f7018c21STomi Valkeinen #include <linux/types.h> 36*f7018c21STomi Valkeinen #include <asm/io.h> 37*f7018c21STomi Valkeinen 38*f7018c21STomi Valkeinen #include "sis.h" 39*f7018c21STomi Valkeinen #include "sis_accel.h" 40*f7018c21STomi Valkeinen 41*f7018c21STomi Valkeinen static const u8 sisALUConv[] = 42*f7018c21STomi Valkeinen { 43*f7018c21STomi Valkeinen 0x00, /* dest = 0; 0, GXclear, 0 */ 44*f7018c21STomi Valkeinen 0x88, /* dest &= src; DSa, GXand, 0x1 */ 45*f7018c21STomi Valkeinen 0x44, /* dest = src & ~dest; SDna, GXandReverse, 0x2 */ 46*f7018c21STomi Valkeinen 0xCC, /* dest = src; S, GXcopy, 0x3 */ 47*f7018c21STomi Valkeinen 0x22, /* dest &= ~src; DSna, GXandInverted, 0x4 */ 48*f7018c21STomi Valkeinen 0xAA, /* dest = dest; D, GXnoop, 0x5 */ 49*f7018c21STomi Valkeinen 0x66, /* dest = ^src; DSx, GXxor, 0x6 */ 50*f7018c21STomi Valkeinen 0xEE, /* dest |= src; DSo, GXor, 0x7 */ 51*f7018c21STomi Valkeinen 0x11, /* dest = ~src & ~dest; DSon, GXnor, 0x8 */ 52*f7018c21STomi Valkeinen 0x99, /* dest ^= ~src ; DSxn, GXequiv, 0x9 */ 53*f7018c21STomi Valkeinen 0x55, /* dest = ~dest; Dn, GXInvert, 0xA */ 54*f7018c21STomi Valkeinen 0xDD, /* dest = src|~dest ; SDno, GXorReverse, 0xB */ 55*f7018c21STomi Valkeinen 0x33, /* dest = ~src; Sn, GXcopyInverted, 0xC */ 56*f7018c21STomi Valkeinen 0xBB, /* dest |= ~src; DSno, GXorInverted, 0xD */ 57*f7018c21STomi Valkeinen 0x77, /* dest = ~src|~dest; DSan, GXnand, 0xE */ 58*f7018c21STomi Valkeinen 0xFF, /* dest = 0xFF; 1, GXset, 0xF */ 59*f7018c21STomi Valkeinen }; 60*f7018c21STomi Valkeinen /* same ROP but with Pattern as Source */ 61*f7018c21STomi Valkeinen static const u8 sisPatALUConv[] = 62*f7018c21STomi Valkeinen { 63*f7018c21STomi Valkeinen 0x00, /* dest = 0; 0, GXclear, 0 */ 64*f7018c21STomi Valkeinen 0xA0, /* dest &= src; DPa, GXand, 0x1 */ 65*f7018c21STomi Valkeinen 0x50, /* dest = src & ~dest; PDna, GXandReverse, 0x2 */ 66*f7018c21STomi Valkeinen 0xF0, /* dest = src; P, GXcopy, 0x3 */ 67*f7018c21STomi Valkeinen 0x0A, /* dest &= ~src; DPna, GXandInverted, 0x4 */ 68*f7018c21STomi Valkeinen 0xAA, /* dest = dest; D, GXnoop, 0x5 */ 69*f7018c21STomi Valkeinen 0x5A, /* dest = ^src; DPx, GXxor, 0x6 */ 70*f7018c21STomi Valkeinen 0xFA, /* dest |= src; DPo, GXor, 0x7 */ 71*f7018c21STomi Valkeinen 0x05, /* dest = ~src & ~dest; DPon, GXnor, 0x8 */ 72*f7018c21STomi Valkeinen 0xA5, /* dest ^= ~src ; DPxn, GXequiv, 0x9 */ 73*f7018c21STomi Valkeinen 0x55, /* dest = ~dest; Dn, GXInvert, 0xA */ 74*f7018c21STomi Valkeinen 0xF5, /* dest = src|~dest ; PDno, GXorReverse, 0xB */ 75*f7018c21STomi Valkeinen 0x0F, /* dest = ~src; Pn, GXcopyInverted, 0xC */ 76*f7018c21STomi Valkeinen 0xAF, /* dest |= ~src; DPno, GXorInverted, 0xD */ 77*f7018c21STomi Valkeinen 0x5F, /* dest = ~src|~dest; DPan, GXnand, 0xE */ 78*f7018c21STomi Valkeinen 0xFF, /* dest = 0xFF; 1, GXset, 0xF */ 79*f7018c21STomi Valkeinen }; 80*f7018c21STomi Valkeinen 81*f7018c21STomi Valkeinen static const int myrops[] = { 82*f7018c21STomi Valkeinen 3, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 83*f7018c21STomi Valkeinen }; 84*f7018c21STomi Valkeinen 85*f7018c21STomi Valkeinen /* 300 series ----------------------------------------------------- */ 86*f7018c21STomi Valkeinen #ifdef CONFIG_FB_SIS_300 87*f7018c21STomi Valkeinen static void 88*f7018c21STomi Valkeinen SiS300Sync(struct sis_video_info *ivideo) 89*f7018c21STomi Valkeinen { 90*f7018c21STomi Valkeinen SiS300Idle 91*f7018c21STomi Valkeinen } 92*f7018c21STomi Valkeinen 93*f7018c21STomi Valkeinen static void 94*f7018c21STomi Valkeinen SiS300SetupForScreenToScreenCopy(struct sis_video_info *ivideo, int xdir, int ydir, 95*f7018c21STomi Valkeinen int rop, int trans_color) 96*f7018c21STomi Valkeinen { 97*f7018c21STomi Valkeinen SiS300SetupDSTColorDepth(ivideo->DstColor); 98*f7018c21STomi Valkeinen SiS300SetupSRCPitch(ivideo->video_linelength) 99*f7018c21STomi Valkeinen SiS300SetupDSTRect(ivideo->video_linelength, 0xffff) 100*f7018c21STomi Valkeinen 101*f7018c21STomi Valkeinen if(trans_color != -1) { 102*f7018c21STomi Valkeinen SiS300SetupROP(0x0A) 103*f7018c21STomi Valkeinen SiS300SetupSRCTrans(trans_color) 104*f7018c21STomi Valkeinen SiS300SetupCMDFlag(TRANSPARENT_BITBLT) 105*f7018c21STomi Valkeinen } else { 106*f7018c21STomi Valkeinen SiS300SetupROP(sisALUConv[rop]) 107*f7018c21STomi Valkeinen } 108*f7018c21STomi Valkeinen if(xdir > 0) { 109*f7018c21STomi Valkeinen SiS300SetupCMDFlag(X_INC) 110*f7018c21STomi Valkeinen } 111*f7018c21STomi Valkeinen if(ydir > 0) { 112*f7018c21STomi Valkeinen SiS300SetupCMDFlag(Y_INC) 113*f7018c21STomi Valkeinen } 114*f7018c21STomi Valkeinen } 115*f7018c21STomi Valkeinen 116*f7018c21STomi Valkeinen static void 117*f7018c21STomi Valkeinen SiS300SubsequentScreenToScreenCopy(struct sis_video_info *ivideo, int src_x, 118*f7018c21STomi Valkeinen int src_y, int dst_x, int dst_y, int width, int height) 119*f7018c21STomi Valkeinen { 120*f7018c21STomi Valkeinen u32 srcbase = 0, dstbase = 0; 121*f7018c21STomi Valkeinen 122*f7018c21STomi Valkeinen if(src_y >= 2048) { 123*f7018c21STomi Valkeinen srcbase = ivideo->video_linelength * src_y; 124*f7018c21STomi Valkeinen src_y = 0; 125*f7018c21STomi Valkeinen } 126*f7018c21STomi Valkeinen if(dst_y >= 2048) { 127*f7018c21STomi Valkeinen dstbase = ivideo->video_linelength * dst_y; 128*f7018c21STomi Valkeinen dst_y = 0; 129*f7018c21STomi Valkeinen } 130*f7018c21STomi Valkeinen 131*f7018c21STomi Valkeinen SiS300SetupSRCBase(srcbase); 132*f7018c21STomi Valkeinen SiS300SetupDSTBase(dstbase); 133*f7018c21STomi Valkeinen 134*f7018c21STomi Valkeinen if(!(ivideo->CommandReg & X_INC)) { 135*f7018c21STomi Valkeinen src_x += width-1; 136*f7018c21STomi Valkeinen dst_x += width-1; 137*f7018c21STomi Valkeinen } 138*f7018c21STomi Valkeinen if(!(ivideo->CommandReg & Y_INC)) { 139*f7018c21STomi Valkeinen src_y += height-1; 140*f7018c21STomi Valkeinen dst_y += height-1; 141*f7018c21STomi Valkeinen } 142*f7018c21STomi Valkeinen SiS300SetupRect(width, height) 143*f7018c21STomi Valkeinen SiS300SetupSRCXY(src_x, src_y) 144*f7018c21STomi Valkeinen SiS300SetupDSTXY(dst_x, dst_y) 145*f7018c21STomi Valkeinen SiS300DoCMD 146*f7018c21STomi Valkeinen } 147*f7018c21STomi Valkeinen 148*f7018c21STomi Valkeinen static void 149*f7018c21STomi Valkeinen SiS300SetupForSolidFill(struct sis_video_info *ivideo, u32 color, int rop) 150*f7018c21STomi Valkeinen { 151*f7018c21STomi Valkeinen SiS300SetupPATFG(color) 152*f7018c21STomi Valkeinen SiS300SetupDSTRect(ivideo->video_linelength, 0xffff) 153*f7018c21STomi Valkeinen SiS300SetupDSTColorDepth(ivideo->DstColor); 154*f7018c21STomi Valkeinen SiS300SetupROP(sisPatALUConv[rop]) 155*f7018c21STomi Valkeinen SiS300SetupCMDFlag(PATFG) 156*f7018c21STomi Valkeinen } 157*f7018c21STomi Valkeinen 158*f7018c21STomi Valkeinen static void 159*f7018c21STomi Valkeinen SiS300SubsequentSolidFillRect(struct sis_video_info *ivideo, int x, int y, int w, int h) 160*f7018c21STomi Valkeinen { 161*f7018c21STomi Valkeinen u32 dstbase = 0; 162*f7018c21STomi Valkeinen 163*f7018c21STomi Valkeinen if(y >= 2048) { 164*f7018c21STomi Valkeinen dstbase = ivideo->video_linelength * y; 165*f7018c21STomi Valkeinen y = 0; 166*f7018c21STomi Valkeinen } 167*f7018c21STomi Valkeinen SiS300SetupDSTBase(dstbase) 168*f7018c21STomi Valkeinen SiS300SetupDSTXY(x,y) 169*f7018c21STomi Valkeinen SiS300SetupRect(w,h) 170*f7018c21STomi Valkeinen SiS300SetupCMDFlag(X_INC | Y_INC | BITBLT) 171*f7018c21STomi Valkeinen SiS300DoCMD 172*f7018c21STomi Valkeinen } 173*f7018c21STomi Valkeinen #endif 174*f7018c21STomi Valkeinen 175*f7018c21STomi Valkeinen /* 315/330/340 series ---------------------------------------------- */ 176*f7018c21STomi Valkeinen 177*f7018c21STomi Valkeinen #ifdef CONFIG_FB_SIS_315 178*f7018c21STomi Valkeinen static void 179*f7018c21STomi Valkeinen SiS310Sync(struct sis_video_info *ivideo) 180*f7018c21STomi Valkeinen { 181*f7018c21STomi Valkeinen SiS310Idle 182*f7018c21STomi Valkeinen } 183*f7018c21STomi Valkeinen 184*f7018c21STomi Valkeinen static void 185*f7018c21STomi Valkeinen SiS310SetupForScreenToScreenCopy(struct sis_video_info *ivideo, int rop, int trans_color) 186*f7018c21STomi Valkeinen { 187*f7018c21STomi Valkeinen SiS310SetupDSTColorDepth(ivideo->DstColor); 188*f7018c21STomi Valkeinen SiS310SetupSRCPitch(ivideo->video_linelength) 189*f7018c21STomi Valkeinen SiS310SetupDSTRect(ivideo->video_linelength, 0x0fff) 190*f7018c21STomi Valkeinen if(trans_color != -1) { 191*f7018c21STomi Valkeinen SiS310SetupROP(0x0A) 192*f7018c21STomi Valkeinen SiS310SetupSRCTrans(trans_color) 193*f7018c21STomi Valkeinen SiS310SetupCMDFlag(TRANSPARENT_BITBLT) 194*f7018c21STomi Valkeinen } else { 195*f7018c21STomi Valkeinen SiS310SetupROP(sisALUConv[rop]) 196*f7018c21STomi Valkeinen /* Set command - not needed, both 0 */ 197*f7018c21STomi Valkeinen /* SiSSetupCMDFlag(BITBLT | SRCVIDEO) */ 198*f7018c21STomi Valkeinen } 199*f7018c21STomi Valkeinen SiS310SetupCMDFlag(ivideo->SiS310_AccelDepth) 200*f7018c21STomi Valkeinen /* The chip is smart enough to know the direction */ 201*f7018c21STomi Valkeinen } 202*f7018c21STomi Valkeinen 203*f7018c21STomi Valkeinen static void 204*f7018c21STomi Valkeinen SiS310SubsequentScreenToScreenCopy(struct sis_video_info *ivideo, int src_x, int src_y, 205*f7018c21STomi Valkeinen int dst_x, int dst_y, int width, int height) 206*f7018c21STomi Valkeinen { 207*f7018c21STomi Valkeinen u32 srcbase = 0, dstbase = 0; 208*f7018c21STomi Valkeinen int mymin = min(src_y, dst_y); 209*f7018c21STomi Valkeinen int mymax = max(src_y, dst_y); 210*f7018c21STomi Valkeinen 211*f7018c21STomi Valkeinen /* Although the chip knows the direction to use 212*f7018c21STomi Valkeinen * if the source and destination areas overlap, 213*f7018c21STomi Valkeinen * that logic fails if we fiddle with the bitmap 214*f7018c21STomi Valkeinen * addresses. Therefore, we check if the source 215*f7018c21STomi Valkeinen * and destination blitting areas overlap and 216*f7018c21STomi Valkeinen * adapt the bitmap addresses synchronously 217*f7018c21STomi Valkeinen * if the coordinates exceed the valid range. 218*f7018c21STomi Valkeinen * The the areas do not overlap, we do our 219*f7018c21STomi Valkeinen * normal check. 220*f7018c21STomi Valkeinen */ 221*f7018c21STomi Valkeinen if((mymax - mymin) < height) { 222*f7018c21STomi Valkeinen if((src_y >= 2048) || (dst_y >= 2048)) { 223*f7018c21STomi Valkeinen srcbase = ivideo->video_linelength * mymin; 224*f7018c21STomi Valkeinen dstbase = ivideo->video_linelength * mymin; 225*f7018c21STomi Valkeinen src_y -= mymin; 226*f7018c21STomi Valkeinen dst_y -= mymin; 227*f7018c21STomi Valkeinen } 228*f7018c21STomi Valkeinen } else { 229*f7018c21STomi Valkeinen if(src_y >= 2048) { 230*f7018c21STomi Valkeinen srcbase = ivideo->video_linelength * src_y; 231*f7018c21STomi Valkeinen src_y = 0; 232*f7018c21STomi Valkeinen } 233*f7018c21STomi Valkeinen if(dst_y >= 2048) { 234*f7018c21STomi Valkeinen dstbase = ivideo->video_linelength * dst_y; 235*f7018c21STomi Valkeinen dst_y = 0; 236*f7018c21STomi Valkeinen } 237*f7018c21STomi Valkeinen } 238*f7018c21STomi Valkeinen 239*f7018c21STomi Valkeinen srcbase += ivideo->video_offset; 240*f7018c21STomi Valkeinen dstbase += ivideo->video_offset; 241*f7018c21STomi Valkeinen 242*f7018c21STomi Valkeinen SiS310SetupSRCBase(srcbase); 243*f7018c21STomi Valkeinen SiS310SetupDSTBase(dstbase); 244*f7018c21STomi Valkeinen SiS310SetupRect(width, height) 245*f7018c21STomi Valkeinen SiS310SetupSRCXY(src_x, src_y) 246*f7018c21STomi Valkeinen SiS310SetupDSTXY(dst_x, dst_y) 247*f7018c21STomi Valkeinen SiS310DoCMD 248*f7018c21STomi Valkeinen } 249*f7018c21STomi Valkeinen 250*f7018c21STomi Valkeinen static void 251*f7018c21STomi Valkeinen SiS310SetupForSolidFill(struct sis_video_info *ivideo, u32 color, int rop) 252*f7018c21STomi Valkeinen { 253*f7018c21STomi Valkeinen SiS310SetupPATFG(color) 254*f7018c21STomi Valkeinen SiS310SetupDSTRect(ivideo->video_linelength, 0x0fff) 255*f7018c21STomi Valkeinen SiS310SetupDSTColorDepth(ivideo->DstColor); 256*f7018c21STomi Valkeinen SiS310SetupROP(sisPatALUConv[rop]) 257*f7018c21STomi Valkeinen SiS310SetupCMDFlag(PATFG | ivideo->SiS310_AccelDepth) 258*f7018c21STomi Valkeinen } 259*f7018c21STomi Valkeinen 260*f7018c21STomi Valkeinen static void 261*f7018c21STomi Valkeinen SiS310SubsequentSolidFillRect(struct sis_video_info *ivideo, int x, int y, int w, int h) 262*f7018c21STomi Valkeinen { 263*f7018c21STomi Valkeinen u32 dstbase = 0; 264*f7018c21STomi Valkeinen 265*f7018c21STomi Valkeinen if(y >= 2048) { 266*f7018c21STomi Valkeinen dstbase = ivideo->video_linelength * y; 267*f7018c21STomi Valkeinen y = 0; 268*f7018c21STomi Valkeinen } 269*f7018c21STomi Valkeinen dstbase += ivideo->video_offset; 270*f7018c21STomi Valkeinen SiS310SetupDSTBase(dstbase) 271*f7018c21STomi Valkeinen SiS310SetupDSTXY(x,y) 272*f7018c21STomi Valkeinen SiS310SetupRect(w,h) 273*f7018c21STomi Valkeinen SiS310SetupCMDFlag(BITBLT) 274*f7018c21STomi Valkeinen SiS310DoCMD 275*f7018c21STomi Valkeinen } 276*f7018c21STomi Valkeinen #endif 277*f7018c21STomi Valkeinen 278*f7018c21STomi Valkeinen /* --------------------------------------------------------------------- */ 279*f7018c21STomi Valkeinen 280*f7018c21STomi Valkeinen /* The exported routines */ 281*f7018c21STomi Valkeinen 282*f7018c21STomi Valkeinen int sisfb_initaccel(struct sis_video_info *ivideo) 283*f7018c21STomi Valkeinen { 284*f7018c21STomi Valkeinen #ifdef SISFB_USE_SPINLOCKS 285*f7018c21STomi Valkeinen spin_lock_init(&ivideo->lockaccel); 286*f7018c21STomi Valkeinen #endif 287*f7018c21STomi Valkeinen return 0; 288*f7018c21STomi Valkeinen } 289*f7018c21STomi Valkeinen 290*f7018c21STomi Valkeinen void sisfb_syncaccel(struct sis_video_info *ivideo) 291*f7018c21STomi Valkeinen { 292*f7018c21STomi Valkeinen if(ivideo->sisvga_engine == SIS_300_VGA) { 293*f7018c21STomi Valkeinen #ifdef CONFIG_FB_SIS_300 294*f7018c21STomi Valkeinen SiS300Sync(ivideo); 295*f7018c21STomi Valkeinen #endif 296*f7018c21STomi Valkeinen } else { 297*f7018c21STomi Valkeinen #ifdef CONFIG_FB_SIS_315 298*f7018c21STomi Valkeinen SiS310Sync(ivideo); 299*f7018c21STomi Valkeinen #endif 300*f7018c21STomi Valkeinen } 301*f7018c21STomi Valkeinen } 302*f7018c21STomi Valkeinen 303*f7018c21STomi Valkeinen int fbcon_sis_sync(struct fb_info *info) 304*f7018c21STomi Valkeinen { 305*f7018c21STomi Valkeinen struct sis_video_info *ivideo = (struct sis_video_info *)info->par; 306*f7018c21STomi Valkeinen CRITFLAGS 307*f7018c21STomi Valkeinen 308*f7018c21STomi Valkeinen if((!ivideo->accel) || (!ivideo->engineok)) 309*f7018c21STomi Valkeinen return 0; 310*f7018c21STomi Valkeinen 311*f7018c21STomi Valkeinen CRITBEGIN 312*f7018c21STomi Valkeinen sisfb_syncaccel(ivideo); 313*f7018c21STomi Valkeinen CRITEND 314*f7018c21STomi Valkeinen 315*f7018c21STomi Valkeinen return 0; 316*f7018c21STomi Valkeinen } 317*f7018c21STomi Valkeinen 318*f7018c21STomi Valkeinen void fbcon_sis_fillrect(struct fb_info *info, const struct fb_fillrect *rect) 319*f7018c21STomi Valkeinen { 320*f7018c21STomi Valkeinen struct sis_video_info *ivideo = (struct sis_video_info *)info->par; 321*f7018c21STomi Valkeinen u32 col = 0; 322*f7018c21STomi Valkeinen u32 vxres = info->var.xres_virtual; 323*f7018c21STomi Valkeinen u32 vyres = info->var.yres_virtual; 324*f7018c21STomi Valkeinen int width, height; 325*f7018c21STomi Valkeinen CRITFLAGS 326*f7018c21STomi Valkeinen 327*f7018c21STomi Valkeinen if(info->state != FBINFO_STATE_RUNNING) 328*f7018c21STomi Valkeinen return; 329*f7018c21STomi Valkeinen 330*f7018c21STomi Valkeinen if((!ivideo->accel) || (!ivideo->engineok)) { 331*f7018c21STomi Valkeinen cfb_fillrect(info, rect); 332*f7018c21STomi Valkeinen return; 333*f7018c21STomi Valkeinen } 334*f7018c21STomi Valkeinen 335*f7018c21STomi Valkeinen if(!rect->width || !rect->height || rect->dx >= vxres || rect->dy >= vyres) 336*f7018c21STomi Valkeinen return; 337*f7018c21STomi Valkeinen 338*f7018c21STomi Valkeinen /* Clipping */ 339*f7018c21STomi Valkeinen width = ((rect->dx + rect->width) > vxres) ? (vxres - rect->dx) : rect->width; 340*f7018c21STomi Valkeinen height = ((rect->dy + rect->height) > vyres) ? (vyres - rect->dy) : rect->height; 341*f7018c21STomi Valkeinen 342*f7018c21STomi Valkeinen switch(info->var.bits_per_pixel) { 343*f7018c21STomi Valkeinen case 8: col = rect->color; 344*f7018c21STomi Valkeinen break; 345*f7018c21STomi Valkeinen case 16: 346*f7018c21STomi Valkeinen case 32: col = ((u32 *)(info->pseudo_palette))[rect->color]; 347*f7018c21STomi Valkeinen break; 348*f7018c21STomi Valkeinen } 349*f7018c21STomi Valkeinen 350*f7018c21STomi Valkeinen if(ivideo->sisvga_engine == SIS_300_VGA) { 351*f7018c21STomi Valkeinen #ifdef CONFIG_FB_SIS_300 352*f7018c21STomi Valkeinen CRITBEGIN 353*f7018c21STomi Valkeinen SiS300SetupForSolidFill(ivideo, col, myrops[rect->rop]); 354*f7018c21STomi Valkeinen SiS300SubsequentSolidFillRect(ivideo, rect->dx, rect->dy, width, height); 355*f7018c21STomi Valkeinen CRITEND 356*f7018c21STomi Valkeinen #endif 357*f7018c21STomi Valkeinen } else { 358*f7018c21STomi Valkeinen #ifdef CONFIG_FB_SIS_315 359*f7018c21STomi Valkeinen CRITBEGIN 360*f7018c21STomi Valkeinen SiS310SetupForSolidFill(ivideo, col, myrops[rect->rop]); 361*f7018c21STomi Valkeinen SiS310SubsequentSolidFillRect(ivideo, rect->dx, rect->dy, width, height); 362*f7018c21STomi Valkeinen CRITEND 363*f7018c21STomi Valkeinen #endif 364*f7018c21STomi Valkeinen } 365*f7018c21STomi Valkeinen 366*f7018c21STomi Valkeinen sisfb_syncaccel(ivideo); 367*f7018c21STomi Valkeinen } 368*f7018c21STomi Valkeinen 369*f7018c21STomi Valkeinen void fbcon_sis_copyarea(struct fb_info *info, const struct fb_copyarea *area) 370*f7018c21STomi Valkeinen { 371*f7018c21STomi Valkeinen struct sis_video_info *ivideo = (struct sis_video_info *)info->par; 372*f7018c21STomi Valkeinen u32 vxres = info->var.xres_virtual; 373*f7018c21STomi Valkeinen u32 vyres = info->var.yres_virtual; 374*f7018c21STomi Valkeinen int width = area->width; 375*f7018c21STomi Valkeinen int height = area->height; 376*f7018c21STomi Valkeinen CRITFLAGS 377*f7018c21STomi Valkeinen 378*f7018c21STomi Valkeinen if(info->state != FBINFO_STATE_RUNNING) 379*f7018c21STomi Valkeinen return; 380*f7018c21STomi Valkeinen 381*f7018c21STomi Valkeinen if((!ivideo->accel) || (!ivideo->engineok)) { 382*f7018c21STomi Valkeinen cfb_copyarea(info, area); 383*f7018c21STomi Valkeinen return; 384*f7018c21STomi Valkeinen } 385*f7018c21STomi Valkeinen 386*f7018c21STomi Valkeinen if(!width || !height || 387*f7018c21STomi Valkeinen area->sx >= vxres || area->sy >= vyres || 388*f7018c21STomi Valkeinen area->dx >= vxres || area->dy >= vyres) 389*f7018c21STomi Valkeinen return; 390*f7018c21STomi Valkeinen 391*f7018c21STomi Valkeinen /* Clipping */ 392*f7018c21STomi Valkeinen if((area->sx + width) > vxres) width = vxres - area->sx; 393*f7018c21STomi Valkeinen if((area->dx + width) > vxres) width = vxres - area->dx; 394*f7018c21STomi Valkeinen if((area->sy + height) > vyres) height = vyres - area->sy; 395*f7018c21STomi Valkeinen if((area->dy + height) > vyres) height = vyres - area->dy; 396*f7018c21STomi Valkeinen 397*f7018c21STomi Valkeinen if(ivideo->sisvga_engine == SIS_300_VGA) { 398*f7018c21STomi Valkeinen #ifdef CONFIG_FB_SIS_300 399*f7018c21STomi Valkeinen int xdir, ydir; 400*f7018c21STomi Valkeinen 401*f7018c21STomi Valkeinen if(area->sx < area->dx) xdir = 0; 402*f7018c21STomi Valkeinen else xdir = 1; 403*f7018c21STomi Valkeinen if(area->sy < area->dy) ydir = 0; 404*f7018c21STomi Valkeinen else ydir = 1; 405*f7018c21STomi Valkeinen 406*f7018c21STomi Valkeinen CRITBEGIN 407*f7018c21STomi Valkeinen SiS300SetupForScreenToScreenCopy(ivideo, xdir, ydir, 3, -1); 408*f7018c21STomi Valkeinen SiS300SubsequentScreenToScreenCopy(ivideo, area->sx, area->sy, 409*f7018c21STomi Valkeinen area->dx, area->dy, width, height); 410*f7018c21STomi Valkeinen CRITEND 411*f7018c21STomi Valkeinen #endif 412*f7018c21STomi Valkeinen } else { 413*f7018c21STomi Valkeinen #ifdef CONFIG_FB_SIS_315 414*f7018c21STomi Valkeinen CRITBEGIN 415*f7018c21STomi Valkeinen SiS310SetupForScreenToScreenCopy(ivideo, 3, -1); 416*f7018c21STomi Valkeinen SiS310SubsequentScreenToScreenCopy(ivideo, area->sx, area->sy, 417*f7018c21STomi Valkeinen area->dx, area->dy, width, height); 418*f7018c21STomi Valkeinen CRITEND 419*f7018c21STomi Valkeinen #endif 420*f7018c21STomi Valkeinen } 421*f7018c21STomi Valkeinen 422*f7018c21STomi Valkeinen sisfb_syncaccel(ivideo); 423*f7018c21STomi Valkeinen } 424