162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * SiS 300/540/630[S]/730[S], 462306a36Sopenharmony_ci * SiS 315[E|PRO]/550/[M]650/651/[M]661[F|M]X/740/[M]741[GX]/330/[M]760[GX], 562306a36Sopenharmony_ci * XGI V3XT/V5/V8, Z7 662306a36Sopenharmony_ci * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * 2D acceleration part 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * Based on the XFree86/X.org driver which is 1162306a36Sopenharmony_ci * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * Author: Thomas Winischhofer <thomas@winischhofer.net> 1462306a36Sopenharmony_ci * (see http://www.winischhofer.net/ 1562306a36Sopenharmony_ci * for more information and updates) 1662306a36Sopenharmony_ci */ 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#include <linux/module.h> 1962306a36Sopenharmony_ci#include <linux/kernel.h> 2062306a36Sopenharmony_ci#include <linux/fb.h> 2162306a36Sopenharmony_ci#include <linux/ioport.h> 2262306a36Sopenharmony_ci#include <linux/types.h> 2362306a36Sopenharmony_ci#include <asm/io.h> 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#include "sis.h" 2662306a36Sopenharmony_ci#include "sis_accel.h" 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistatic const u8 sisALUConv[] = 2962306a36Sopenharmony_ci{ 3062306a36Sopenharmony_ci 0x00, /* dest = 0; 0, GXclear, 0 */ 3162306a36Sopenharmony_ci 0x88, /* dest &= src; DSa, GXand, 0x1 */ 3262306a36Sopenharmony_ci 0x44, /* dest = src & ~dest; SDna, GXandReverse, 0x2 */ 3362306a36Sopenharmony_ci 0xCC, /* dest = src; S, GXcopy, 0x3 */ 3462306a36Sopenharmony_ci 0x22, /* dest &= ~src; DSna, GXandInverted, 0x4 */ 3562306a36Sopenharmony_ci 0xAA, /* dest = dest; D, GXnoop, 0x5 */ 3662306a36Sopenharmony_ci 0x66, /* dest = ^src; DSx, GXxor, 0x6 */ 3762306a36Sopenharmony_ci 0xEE, /* dest |= src; DSo, GXor, 0x7 */ 3862306a36Sopenharmony_ci 0x11, /* dest = ~src & ~dest; DSon, GXnor, 0x8 */ 3962306a36Sopenharmony_ci 0x99, /* dest ^= ~src ; DSxn, GXequiv, 0x9 */ 4062306a36Sopenharmony_ci 0x55, /* dest = ~dest; Dn, GXInvert, 0xA */ 4162306a36Sopenharmony_ci 0xDD, /* dest = src|~dest ; SDno, GXorReverse, 0xB */ 4262306a36Sopenharmony_ci 0x33, /* dest = ~src; Sn, GXcopyInverted, 0xC */ 4362306a36Sopenharmony_ci 0xBB, /* dest |= ~src; DSno, GXorInverted, 0xD */ 4462306a36Sopenharmony_ci 0x77, /* dest = ~src|~dest; DSan, GXnand, 0xE */ 4562306a36Sopenharmony_ci 0xFF, /* dest = 0xFF; 1, GXset, 0xF */ 4662306a36Sopenharmony_ci}; 4762306a36Sopenharmony_ci/* same ROP but with Pattern as Source */ 4862306a36Sopenharmony_cistatic const u8 sisPatALUConv[] = 4962306a36Sopenharmony_ci{ 5062306a36Sopenharmony_ci 0x00, /* dest = 0; 0, GXclear, 0 */ 5162306a36Sopenharmony_ci 0xA0, /* dest &= src; DPa, GXand, 0x1 */ 5262306a36Sopenharmony_ci 0x50, /* dest = src & ~dest; PDna, GXandReverse, 0x2 */ 5362306a36Sopenharmony_ci 0xF0, /* dest = src; P, GXcopy, 0x3 */ 5462306a36Sopenharmony_ci 0x0A, /* dest &= ~src; DPna, GXandInverted, 0x4 */ 5562306a36Sopenharmony_ci 0xAA, /* dest = dest; D, GXnoop, 0x5 */ 5662306a36Sopenharmony_ci 0x5A, /* dest = ^src; DPx, GXxor, 0x6 */ 5762306a36Sopenharmony_ci 0xFA, /* dest |= src; DPo, GXor, 0x7 */ 5862306a36Sopenharmony_ci 0x05, /* dest = ~src & ~dest; DPon, GXnor, 0x8 */ 5962306a36Sopenharmony_ci 0xA5, /* dest ^= ~src ; DPxn, GXequiv, 0x9 */ 6062306a36Sopenharmony_ci 0x55, /* dest = ~dest; Dn, GXInvert, 0xA */ 6162306a36Sopenharmony_ci 0xF5, /* dest = src|~dest ; PDno, GXorReverse, 0xB */ 6262306a36Sopenharmony_ci 0x0F, /* dest = ~src; Pn, GXcopyInverted, 0xC */ 6362306a36Sopenharmony_ci 0xAF, /* dest |= ~src; DPno, GXorInverted, 0xD */ 6462306a36Sopenharmony_ci 0x5F, /* dest = ~src|~dest; DPan, GXnand, 0xE */ 6562306a36Sopenharmony_ci 0xFF, /* dest = 0xFF; 1, GXset, 0xF */ 6662306a36Sopenharmony_ci}; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_cistatic const int myrops[] = { 6962306a36Sopenharmony_ci 3, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 7062306a36Sopenharmony_ci}; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci/* 300 series ----------------------------------------------------- */ 7362306a36Sopenharmony_ci#ifdef CONFIG_FB_SIS_300 7462306a36Sopenharmony_cistatic void 7562306a36Sopenharmony_ciSiS300Sync(struct sis_video_info *ivideo) 7662306a36Sopenharmony_ci{ 7762306a36Sopenharmony_ci SiS300Idle 7862306a36Sopenharmony_ci} 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_cistatic void 8162306a36Sopenharmony_ciSiS300SetupForScreenToScreenCopy(struct sis_video_info *ivideo, int xdir, int ydir, 8262306a36Sopenharmony_ci int rop, int trans_color) 8362306a36Sopenharmony_ci{ 8462306a36Sopenharmony_ci SiS300SetupDSTColorDepth(ivideo->DstColor); 8562306a36Sopenharmony_ci SiS300SetupSRCPitch(ivideo->video_linelength) 8662306a36Sopenharmony_ci SiS300SetupDSTRect(ivideo->video_linelength, 0xffff) 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci if(trans_color != -1) { 8962306a36Sopenharmony_ci SiS300SetupROP(0x0A) 9062306a36Sopenharmony_ci SiS300SetupSRCTrans(trans_color) 9162306a36Sopenharmony_ci SiS300SetupCMDFlag(TRANSPARENT_BITBLT) 9262306a36Sopenharmony_ci } else { 9362306a36Sopenharmony_ci SiS300SetupROP(sisALUConv[rop]) 9462306a36Sopenharmony_ci } 9562306a36Sopenharmony_ci if(xdir > 0) { 9662306a36Sopenharmony_ci SiS300SetupCMDFlag(X_INC) 9762306a36Sopenharmony_ci } 9862306a36Sopenharmony_ci if(ydir > 0) { 9962306a36Sopenharmony_ci SiS300SetupCMDFlag(Y_INC) 10062306a36Sopenharmony_ci } 10162306a36Sopenharmony_ci} 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_cistatic void 10462306a36Sopenharmony_ciSiS300SubsequentScreenToScreenCopy(struct sis_video_info *ivideo, int src_x, 10562306a36Sopenharmony_ci int src_y, int dst_x, int dst_y, int width, int height) 10662306a36Sopenharmony_ci{ 10762306a36Sopenharmony_ci u32 srcbase = 0, dstbase = 0; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci if(src_y >= 2048) { 11062306a36Sopenharmony_ci srcbase = ivideo->video_linelength * src_y; 11162306a36Sopenharmony_ci src_y = 0; 11262306a36Sopenharmony_ci } 11362306a36Sopenharmony_ci if(dst_y >= 2048) { 11462306a36Sopenharmony_ci dstbase = ivideo->video_linelength * dst_y; 11562306a36Sopenharmony_ci dst_y = 0; 11662306a36Sopenharmony_ci } 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci SiS300SetupSRCBase(srcbase); 11962306a36Sopenharmony_ci SiS300SetupDSTBase(dstbase); 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci if(!(ivideo->CommandReg & X_INC)) { 12262306a36Sopenharmony_ci src_x += width-1; 12362306a36Sopenharmony_ci dst_x += width-1; 12462306a36Sopenharmony_ci } 12562306a36Sopenharmony_ci if(!(ivideo->CommandReg & Y_INC)) { 12662306a36Sopenharmony_ci src_y += height-1; 12762306a36Sopenharmony_ci dst_y += height-1; 12862306a36Sopenharmony_ci } 12962306a36Sopenharmony_ci SiS300SetupRect(width, height) 13062306a36Sopenharmony_ci SiS300SetupSRCXY(src_x, src_y) 13162306a36Sopenharmony_ci SiS300SetupDSTXY(dst_x, dst_y) 13262306a36Sopenharmony_ci SiS300DoCMD 13362306a36Sopenharmony_ci} 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_cistatic void 13662306a36Sopenharmony_ciSiS300SetupForSolidFill(struct sis_video_info *ivideo, u32 color, int rop) 13762306a36Sopenharmony_ci{ 13862306a36Sopenharmony_ci SiS300SetupPATFG(color) 13962306a36Sopenharmony_ci SiS300SetupDSTRect(ivideo->video_linelength, 0xffff) 14062306a36Sopenharmony_ci SiS300SetupDSTColorDepth(ivideo->DstColor); 14162306a36Sopenharmony_ci SiS300SetupROP(sisPatALUConv[rop]) 14262306a36Sopenharmony_ci SiS300SetupCMDFlag(PATFG) 14362306a36Sopenharmony_ci} 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_cistatic void 14662306a36Sopenharmony_ciSiS300SubsequentSolidFillRect(struct sis_video_info *ivideo, int x, int y, int w, int h) 14762306a36Sopenharmony_ci{ 14862306a36Sopenharmony_ci u32 dstbase = 0; 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci if(y >= 2048) { 15162306a36Sopenharmony_ci dstbase = ivideo->video_linelength * y; 15262306a36Sopenharmony_ci y = 0; 15362306a36Sopenharmony_ci } 15462306a36Sopenharmony_ci SiS300SetupDSTBase(dstbase) 15562306a36Sopenharmony_ci SiS300SetupDSTXY(x,y) 15662306a36Sopenharmony_ci SiS300SetupRect(w,h) 15762306a36Sopenharmony_ci SiS300SetupCMDFlag(X_INC | Y_INC | BITBLT) 15862306a36Sopenharmony_ci SiS300DoCMD 15962306a36Sopenharmony_ci} 16062306a36Sopenharmony_ci#endif 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci/* 315/330/340 series ---------------------------------------------- */ 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci#ifdef CONFIG_FB_SIS_315 16562306a36Sopenharmony_cistatic void 16662306a36Sopenharmony_ciSiS310Sync(struct sis_video_info *ivideo) 16762306a36Sopenharmony_ci{ 16862306a36Sopenharmony_ci SiS310Idle 16962306a36Sopenharmony_ci} 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_cistatic void 17262306a36Sopenharmony_ciSiS310SetupForScreenToScreenCopy(struct sis_video_info *ivideo, int rop, int trans_color) 17362306a36Sopenharmony_ci{ 17462306a36Sopenharmony_ci SiS310SetupDSTColorDepth(ivideo->DstColor); 17562306a36Sopenharmony_ci SiS310SetupSRCPitch(ivideo->video_linelength) 17662306a36Sopenharmony_ci SiS310SetupDSTRect(ivideo->video_linelength, 0x0fff) 17762306a36Sopenharmony_ci if(trans_color != -1) { 17862306a36Sopenharmony_ci SiS310SetupROP(0x0A) 17962306a36Sopenharmony_ci SiS310SetupSRCTrans(trans_color) 18062306a36Sopenharmony_ci SiS310SetupCMDFlag(TRANSPARENT_BITBLT) 18162306a36Sopenharmony_ci } else { 18262306a36Sopenharmony_ci SiS310SetupROP(sisALUConv[rop]) 18362306a36Sopenharmony_ci /* Set command - not needed, both 0 */ 18462306a36Sopenharmony_ci /* SiSSetupCMDFlag(BITBLT | SRCVIDEO) */ 18562306a36Sopenharmony_ci } 18662306a36Sopenharmony_ci SiS310SetupCMDFlag(ivideo->SiS310_AccelDepth) 18762306a36Sopenharmony_ci /* The chip is smart enough to know the direction */ 18862306a36Sopenharmony_ci} 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_cistatic void 19162306a36Sopenharmony_ciSiS310SubsequentScreenToScreenCopy(struct sis_video_info *ivideo, int src_x, int src_y, 19262306a36Sopenharmony_ci int dst_x, int dst_y, int width, int height) 19362306a36Sopenharmony_ci{ 19462306a36Sopenharmony_ci u32 srcbase = 0, dstbase = 0; 19562306a36Sopenharmony_ci int mymin = min(src_y, dst_y); 19662306a36Sopenharmony_ci int mymax = max(src_y, dst_y); 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci /* Although the chip knows the direction to use 19962306a36Sopenharmony_ci * if the source and destination areas overlap, 20062306a36Sopenharmony_ci * that logic fails if we fiddle with the bitmap 20162306a36Sopenharmony_ci * addresses. Therefore, we check if the source 20262306a36Sopenharmony_ci * and destination blitting areas overlap and 20362306a36Sopenharmony_ci * adapt the bitmap addresses synchronously 20462306a36Sopenharmony_ci * if the coordinates exceed the valid range. 20562306a36Sopenharmony_ci * The areas do not overlap, we do our 20662306a36Sopenharmony_ci * normal check. 20762306a36Sopenharmony_ci */ 20862306a36Sopenharmony_ci if((mymax - mymin) < height) { 20962306a36Sopenharmony_ci if((src_y >= 2048) || (dst_y >= 2048)) { 21062306a36Sopenharmony_ci srcbase = ivideo->video_linelength * mymin; 21162306a36Sopenharmony_ci dstbase = ivideo->video_linelength * mymin; 21262306a36Sopenharmony_ci src_y -= mymin; 21362306a36Sopenharmony_ci dst_y -= mymin; 21462306a36Sopenharmony_ci } 21562306a36Sopenharmony_ci } else { 21662306a36Sopenharmony_ci if(src_y >= 2048) { 21762306a36Sopenharmony_ci srcbase = ivideo->video_linelength * src_y; 21862306a36Sopenharmony_ci src_y = 0; 21962306a36Sopenharmony_ci } 22062306a36Sopenharmony_ci if(dst_y >= 2048) { 22162306a36Sopenharmony_ci dstbase = ivideo->video_linelength * dst_y; 22262306a36Sopenharmony_ci dst_y = 0; 22362306a36Sopenharmony_ci } 22462306a36Sopenharmony_ci } 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci srcbase += ivideo->video_offset; 22762306a36Sopenharmony_ci dstbase += ivideo->video_offset; 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci SiS310SetupSRCBase(srcbase); 23062306a36Sopenharmony_ci SiS310SetupDSTBase(dstbase); 23162306a36Sopenharmony_ci SiS310SetupRect(width, height) 23262306a36Sopenharmony_ci SiS310SetupSRCXY(src_x, src_y) 23362306a36Sopenharmony_ci SiS310SetupDSTXY(dst_x, dst_y) 23462306a36Sopenharmony_ci SiS310DoCMD 23562306a36Sopenharmony_ci} 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_cistatic void 23862306a36Sopenharmony_ciSiS310SetupForSolidFill(struct sis_video_info *ivideo, u32 color, int rop) 23962306a36Sopenharmony_ci{ 24062306a36Sopenharmony_ci SiS310SetupPATFG(color) 24162306a36Sopenharmony_ci SiS310SetupDSTRect(ivideo->video_linelength, 0x0fff) 24262306a36Sopenharmony_ci SiS310SetupDSTColorDepth(ivideo->DstColor); 24362306a36Sopenharmony_ci SiS310SetupROP(sisPatALUConv[rop]) 24462306a36Sopenharmony_ci SiS310SetupCMDFlag(PATFG | ivideo->SiS310_AccelDepth) 24562306a36Sopenharmony_ci} 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_cistatic void 24862306a36Sopenharmony_ciSiS310SubsequentSolidFillRect(struct sis_video_info *ivideo, int x, int y, int w, int h) 24962306a36Sopenharmony_ci{ 25062306a36Sopenharmony_ci u32 dstbase = 0; 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci if(y >= 2048) { 25362306a36Sopenharmony_ci dstbase = ivideo->video_linelength * y; 25462306a36Sopenharmony_ci y = 0; 25562306a36Sopenharmony_ci } 25662306a36Sopenharmony_ci dstbase += ivideo->video_offset; 25762306a36Sopenharmony_ci SiS310SetupDSTBase(dstbase) 25862306a36Sopenharmony_ci SiS310SetupDSTXY(x,y) 25962306a36Sopenharmony_ci SiS310SetupRect(w,h) 26062306a36Sopenharmony_ci SiS310SetupCMDFlag(BITBLT) 26162306a36Sopenharmony_ci SiS310DoCMD 26262306a36Sopenharmony_ci} 26362306a36Sopenharmony_ci#endif 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci/* --------------------------------------------------------------------- */ 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci/* The exported routines */ 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ciint sisfb_initaccel(struct sis_video_info *ivideo) 27062306a36Sopenharmony_ci{ 27162306a36Sopenharmony_ci#ifdef SISFB_USE_SPINLOCKS 27262306a36Sopenharmony_ci spin_lock_init(&ivideo->lockaccel); 27362306a36Sopenharmony_ci#endif 27462306a36Sopenharmony_ci return 0; 27562306a36Sopenharmony_ci} 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_civoid sisfb_syncaccel(struct sis_video_info *ivideo) 27862306a36Sopenharmony_ci{ 27962306a36Sopenharmony_ci if(ivideo->sisvga_engine == SIS_300_VGA) { 28062306a36Sopenharmony_ci#ifdef CONFIG_FB_SIS_300 28162306a36Sopenharmony_ci SiS300Sync(ivideo); 28262306a36Sopenharmony_ci#endif 28362306a36Sopenharmony_ci } else { 28462306a36Sopenharmony_ci#ifdef CONFIG_FB_SIS_315 28562306a36Sopenharmony_ci SiS310Sync(ivideo); 28662306a36Sopenharmony_ci#endif 28762306a36Sopenharmony_ci } 28862306a36Sopenharmony_ci} 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ciint fbcon_sis_sync(struct fb_info *info) 29162306a36Sopenharmony_ci{ 29262306a36Sopenharmony_ci struct sis_video_info *ivideo = (struct sis_video_info *)info->par; 29362306a36Sopenharmony_ci CRITFLAGS 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci if((!ivideo->accel) || (!ivideo->engineok)) 29662306a36Sopenharmony_ci return 0; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci CRITBEGIN 29962306a36Sopenharmony_ci sisfb_syncaccel(ivideo); 30062306a36Sopenharmony_ci CRITEND 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci return 0; 30362306a36Sopenharmony_ci} 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_civoid fbcon_sis_fillrect(struct fb_info *info, const struct fb_fillrect *rect) 30662306a36Sopenharmony_ci{ 30762306a36Sopenharmony_ci struct sis_video_info *ivideo = (struct sis_video_info *)info->par; 30862306a36Sopenharmony_ci u32 col = 0; 30962306a36Sopenharmony_ci u32 vxres = info->var.xres_virtual; 31062306a36Sopenharmony_ci u32 vyres = info->var.yres_virtual; 31162306a36Sopenharmony_ci int width, height; 31262306a36Sopenharmony_ci CRITFLAGS 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci if(info->state != FBINFO_STATE_RUNNING) 31562306a36Sopenharmony_ci return; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci if((!ivideo->accel) || (!ivideo->engineok)) { 31862306a36Sopenharmony_ci cfb_fillrect(info, rect); 31962306a36Sopenharmony_ci return; 32062306a36Sopenharmony_ci } 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci if(!rect->width || !rect->height || rect->dx >= vxres || rect->dy >= vyres) 32362306a36Sopenharmony_ci return; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci /* Clipping */ 32662306a36Sopenharmony_ci width = ((rect->dx + rect->width) > vxres) ? (vxres - rect->dx) : rect->width; 32762306a36Sopenharmony_ci height = ((rect->dy + rect->height) > vyres) ? (vyres - rect->dy) : rect->height; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci switch(info->var.bits_per_pixel) { 33062306a36Sopenharmony_ci case 8: col = rect->color; 33162306a36Sopenharmony_ci break; 33262306a36Sopenharmony_ci case 16: 33362306a36Sopenharmony_ci case 32: col = ((u32 *)(info->pseudo_palette))[rect->color]; 33462306a36Sopenharmony_ci break; 33562306a36Sopenharmony_ci } 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci if(ivideo->sisvga_engine == SIS_300_VGA) { 33862306a36Sopenharmony_ci#ifdef CONFIG_FB_SIS_300 33962306a36Sopenharmony_ci CRITBEGIN 34062306a36Sopenharmony_ci SiS300SetupForSolidFill(ivideo, col, myrops[rect->rop]); 34162306a36Sopenharmony_ci SiS300SubsequentSolidFillRect(ivideo, rect->dx, rect->dy, width, height); 34262306a36Sopenharmony_ci CRITEND 34362306a36Sopenharmony_ci#endif 34462306a36Sopenharmony_ci } else { 34562306a36Sopenharmony_ci#ifdef CONFIG_FB_SIS_315 34662306a36Sopenharmony_ci CRITBEGIN 34762306a36Sopenharmony_ci SiS310SetupForSolidFill(ivideo, col, myrops[rect->rop]); 34862306a36Sopenharmony_ci SiS310SubsequentSolidFillRect(ivideo, rect->dx, rect->dy, width, height); 34962306a36Sopenharmony_ci CRITEND 35062306a36Sopenharmony_ci#endif 35162306a36Sopenharmony_ci } 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci sisfb_syncaccel(ivideo); 35462306a36Sopenharmony_ci} 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_civoid fbcon_sis_copyarea(struct fb_info *info, const struct fb_copyarea *area) 35762306a36Sopenharmony_ci{ 35862306a36Sopenharmony_ci struct sis_video_info *ivideo = (struct sis_video_info *)info->par; 35962306a36Sopenharmony_ci u32 vxres = info->var.xres_virtual; 36062306a36Sopenharmony_ci u32 vyres = info->var.yres_virtual; 36162306a36Sopenharmony_ci int width = area->width; 36262306a36Sopenharmony_ci int height = area->height; 36362306a36Sopenharmony_ci CRITFLAGS 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci if(info->state != FBINFO_STATE_RUNNING) 36662306a36Sopenharmony_ci return; 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci if((!ivideo->accel) || (!ivideo->engineok)) { 36962306a36Sopenharmony_ci cfb_copyarea(info, area); 37062306a36Sopenharmony_ci return; 37162306a36Sopenharmony_ci } 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci if(!width || !height || 37462306a36Sopenharmony_ci area->sx >= vxres || area->sy >= vyres || 37562306a36Sopenharmony_ci area->dx >= vxres || area->dy >= vyres) 37662306a36Sopenharmony_ci return; 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci /* Clipping */ 37962306a36Sopenharmony_ci if((area->sx + width) > vxres) width = vxres - area->sx; 38062306a36Sopenharmony_ci if((area->dx + width) > vxres) width = vxres - area->dx; 38162306a36Sopenharmony_ci if((area->sy + height) > vyres) height = vyres - area->sy; 38262306a36Sopenharmony_ci if((area->dy + height) > vyres) height = vyres - area->dy; 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci if(ivideo->sisvga_engine == SIS_300_VGA) { 38562306a36Sopenharmony_ci#ifdef CONFIG_FB_SIS_300 38662306a36Sopenharmony_ci int xdir, ydir; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci if(area->sx < area->dx) xdir = 0; 38962306a36Sopenharmony_ci else xdir = 1; 39062306a36Sopenharmony_ci if(area->sy < area->dy) ydir = 0; 39162306a36Sopenharmony_ci else ydir = 1; 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci CRITBEGIN 39462306a36Sopenharmony_ci SiS300SetupForScreenToScreenCopy(ivideo, xdir, ydir, 3, -1); 39562306a36Sopenharmony_ci SiS300SubsequentScreenToScreenCopy(ivideo, area->sx, area->sy, 39662306a36Sopenharmony_ci area->dx, area->dy, width, height); 39762306a36Sopenharmony_ci CRITEND 39862306a36Sopenharmony_ci#endif 39962306a36Sopenharmony_ci } else { 40062306a36Sopenharmony_ci#ifdef CONFIG_FB_SIS_315 40162306a36Sopenharmony_ci CRITBEGIN 40262306a36Sopenharmony_ci SiS310SetupForScreenToScreenCopy(ivideo, 3, -1); 40362306a36Sopenharmony_ci SiS310SubsequentScreenToScreenCopy(ivideo, area->sx, area->sy, 40462306a36Sopenharmony_ci area->dx, area->dy, width, height); 40562306a36Sopenharmony_ci CRITEND 40662306a36Sopenharmony_ci#endif 40762306a36Sopenharmony_ci } 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci sisfb_syncaccel(ivideo); 41062306a36Sopenharmony_ci} 411