Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* |
| 2 | * SiS 300/630/730/540/315/550/650/740 frame buffer driver |
| 3 | * for Linux kernels 2.4.x and 2.5.x |
| 4 | * |
| 5 | * 2D acceleration part |
| 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU General Public License as published by |
| 9 | * the Free Software Foundation; either version 2 of the named License, |
| 10 | * or any later version. |
| 11 | * |
| 12 | * This program is distributed in the hope that it will be useful, |
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | * GNU General Public License for more details. |
| 16 | * |
| 17 | * You should have received a copy of the GNU General Public License |
| 18 | * along with this program; if not, write to the Free Software |
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA |
| 20 | * |
| 21 | * Based on the X driver's sis300_accel.h which is |
| 22 | * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria |
| 23 | * and sis310_accel.h which is |
| 24 | * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria |
| 25 | * |
| 26 | * Author: Thomas Winischhofer <thomas@winischhofer.net>: |
| 27 | * (see http://www.winischhofer.net/ |
| 28 | * for more information and updates) |
| 29 | */ |
| 30 | |
| 31 | #ifndef _SISFB_ACCEL_H |
| 32 | #define _SISFB_ACCEL_H |
| 33 | |
| 34 | /* Guard accelerator accesses with spin_lock_irqsave? Works well without. */ |
| 35 | #undef SISFB_USE_SPINLOCKS |
| 36 | |
| 37 | #ifdef SISFB_USE_SPINLOCKS |
| 38 | #include <linux/spinlock.h> |
| 39 | #define CRITBEGIN spin_lock_irqsave(&ivideo->lockaccel, critflags); |
| 40 | #define CRITEND spin_unlock_irqrestore(&ivideo->lockaccel, critflags); |
| 41 | #define CRITFLAGS unsigned long critflags; |
| 42 | #else |
| 43 | #define CRITBEGIN |
| 44 | #define CRITEND |
| 45 | #define CRITFLAGS |
| 46 | #endif |
| 47 | |
| 48 | /* Definitions for the SIS engine communication. */ |
| 49 | |
| 50 | #define PATREGSIZE 384 /* Pattern register size. 384 bytes @ 0x8300 */ |
| 51 | #define BR(x) (0x8200 | (x) << 2) |
| 52 | #define PBR(x) (0x8300 | (x) << 2) |
| 53 | |
| 54 | /* SiS300 engine commands */ |
| 55 | #define BITBLT 0x00000000 /* Blit */ |
| 56 | #define COLOREXP 0x00000001 /* Color expand */ |
| 57 | #define ENCOLOREXP 0x00000002 /* Enhanced color expand */ |
| 58 | #define MULTIPLE_SCANLINE 0x00000003 /* ? */ |
| 59 | #define LINE 0x00000004 /* Draw line */ |
| 60 | #define TRAPAZOID_FILL 0x00000005 /* Fill trapezoid */ |
| 61 | #define TRANSPARENT_BITBLT 0x00000006 /* Transparent Blit */ |
| 62 | |
| 63 | /* Additional engine commands for 315 */ |
| 64 | #define ALPHA_BLEND 0x00000007 /* Alpha blend ? */ |
| 65 | #define A3D_FUNCTION 0x00000008 /* 3D command ? */ |
| 66 | #define CLEAR_Z_BUFFER 0x00000009 /* ? */ |
| 67 | #define GRADIENT_FILL 0x0000000A /* Gradient fill */ |
| 68 | |
| 69 | /* source select */ |
| 70 | #define SRCVIDEO 0x00000000 /* source is video RAM */ |
| 71 | #define SRCSYSTEM 0x00000010 /* source is system memory */ |
| 72 | #define SRCCPUBLITBUF SRCSYSTEM /* source is CPU-driven BitBuffer (for color expand) */ |
| 73 | #define SRCAGP 0x00000020 /* source is AGP memory (?) */ |
| 74 | |
| 75 | /* Pattern flags */ |
| 76 | #define PATFG 0x00000000 /* foreground color */ |
| 77 | #define PATPATREG 0x00000040 /* pattern in pattern buffer (0x8300) */ |
| 78 | #define PATMONO 0x00000080 /* mono pattern */ |
| 79 | |
| 80 | /* blitting direction (300 series only) */ |
| 81 | #define X_INC 0x00010000 |
| 82 | #define X_DEC 0x00000000 |
| 83 | #define Y_INC 0x00020000 |
| 84 | #define Y_DEC 0x00000000 |
| 85 | |
| 86 | /* Clipping flags */ |
| 87 | #define NOCLIP 0x00000000 |
| 88 | #define NOMERGECLIP 0x04000000 |
| 89 | #define CLIPENABLE 0x00040000 |
| 90 | #define CLIPWITHOUTMERGE 0x04040000 |
| 91 | |
| 92 | /* Transparency */ |
| 93 | #define OPAQUE 0x00000000 |
| 94 | #define TRANSPARENT 0x00100000 |
| 95 | |
| 96 | /* ? */ |
| 97 | #define DSTAGP 0x02000000 |
| 98 | #define DSTVIDEO 0x02000000 |
| 99 | |
| 100 | /* Subfunctions for Color/Enhanced Color Expansion (315 only) */ |
| 101 | #define COLOR_TO_MONO 0x00100000 |
| 102 | #define AA_TEXT 0x00200000 |
| 103 | |
| 104 | /* Some general registers for 315 series */ |
| 105 | #define SRC_ADDR 0x8200 |
| 106 | #define SRC_PITCH 0x8204 |
| 107 | #define AGP_BASE 0x8206 /* color-depth dependent value */ |
| 108 | #define SRC_Y 0x8208 |
| 109 | #define SRC_X 0x820A |
| 110 | #define DST_Y 0x820C |
| 111 | #define DST_X 0x820E |
| 112 | #define DST_ADDR 0x8210 |
| 113 | #define DST_PITCH 0x8214 |
| 114 | #define DST_HEIGHT 0x8216 |
| 115 | #define RECT_WIDTH 0x8218 |
| 116 | #define RECT_HEIGHT 0x821A |
| 117 | #define PAT_FGCOLOR 0x821C |
| 118 | #define PAT_BGCOLOR 0x8220 |
| 119 | #define SRC_FGCOLOR 0x8224 |
| 120 | #define SRC_BGCOLOR 0x8228 |
| 121 | #define MONO_MASK 0x822C |
| 122 | #define LEFT_CLIP 0x8234 |
| 123 | #define TOP_CLIP 0x8236 |
| 124 | #define RIGHT_CLIP 0x8238 |
| 125 | #define BOTTOM_CLIP 0x823A |
| 126 | #define COMMAND_READY 0x823C |
| 127 | #define FIRE_TRIGGER 0x8240 |
| 128 | |
| 129 | #define PATTERN_REG 0x8300 /* 384 bytes pattern buffer */ |
| 130 | |
| 131 | /* Transparent bitblit registers */ |
| 132 | #define TRANS_DST_KEY_HIGH PAT_FGCOLOR |
| 133 | #define TRANS_DST_KEY_LOW PAT_BGCOLOR |
| 134 | #define TRANS_SRC_KEY_HIGH SRC_FGCOLOR |
| 135 | #define TRANS_SRC_KEY_LOW SRC_BGCOLOR |
| 136 | |
| 137 | /* Store queue length in par */ |
| 138 | #define CmdQueLen ivideo->cmdqueuelength |
| 139 | |
| 140 | /* ------------- SiS 300 series -------------- */ |
| 141 | |
| 142 | /* BR(16) (0x8240): |
| 143 | |
| 144 | bit 31 2D engine: 1 is idle, |
| 145 | bit 30 3D engine: 1 is idle, |
| 146 | bit 29 Command queue: 1 is empty |
| 147 | bits 28:24: Current CPU driven BitBlt buffer stage bit[4:0] |
| 148 | bits 15:0: Current command queue length |
| 149 | |
| 150 | */ |
| 151 | |
| 152 | #define SiS300Idle \ |
| 153 | { \ |
| 154 | while((MMIO_IN16(ivideo->mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \ |
| 155 | while((MMIO_IN16(ivideo->mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \ |
| 156 | while((MMIO_IN16(ivideo->mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \ |
| 157 | CmdQueLen = MMIO_IN16(ivideo->mmio_vbase, 0x8240); \ |
| 158 | } |
| 159 | /* (do three times, because 2D engine seems quite unsure about whether or not it's idle) */ |
| 160 | |
| 161 | #define SiS300SetupSRCBase(base) \ |
| 162 | if(CmdQueLen <= 0) SiS300Idle;\ |
| 163 | MMIO_OUT32(ivideo->mmio_vbase, BR(0), base);\ |
| 164 | CmdQueLen--; |
| 165 | |
| 166 | #define SiS300SetupSRCPitch(pitch) \ |
| 167 | if(CmdQueLen <= 0) SiS300Idle;\ |
| 168 | MMIO_OUT16(ivideo->mmio_vbase, BR(1), pitch);\ |
| 169 | CmdQueLen--; |
| 170 | |
| 171 | #define SiS300SetupSRCXY(x,y) \ |
| 172 | if(CmdQueLen <= 0) SiS300Idle;\ |
| 173 | MMIO_OUT32(ivideo->mmio_vbase, BR(2), (x)<<16 | (y) );\ |
| 174 | CmdQueLen--; |
| 175 | |
| 176 | #define SiS300SetupDSTBase(base) \ |
| 177 | if(CmdQueLen <= 0) SiS300Idle;\ |
| 178 | MMIO_OUT32(ivideo->mmio_vbase, BR(4), base);\ |
| 179 | CmdQueLen--; |
| 180 | |
| 181 | #define SiS300SetupDSTXY(x,y) \ |
| 182 | if(CmdQueLen <= 0) SiS300Idle;\ |
| 183 | MMIO_OUT32(ivideo->mmio_vbase, BR(3), (x)<<16 | (y) );\ |
| 184 | CmdQueLen--; |
| 185 | |
| 186 | #define SiS300SetupDSTRect(x,y) \ |
| 187 | if(CmdQueLen <= 0) SiS300Idle;\ |
| 188 | MMIO_OUT32(ivideo->mmio_vbase, BR(5), (y)<<16 | (x) );\ |
| 189 | CmdQueLen--; |
| 190 | |
| 191 | #define SiS300SetupDSTColorDepth(bpp) \ |
| 192 | if(CmdQueLen <= 0) SiS300Idle;\ |
| 193 | MMIO_OUT16(ivideo->mmio_vbase, BR(1)+2, bpp);\ |
| 194 | CmdQueLen--; |
| 195 | |
| 196 | #define SiS300SetupRect(w,h) \ |
| 197 | if(CmdQueLen <= 0) SiS300Idle;\ |
| 198 | MMIO_OUT32(ivideo->mmio_vbase, BR(6), (h)<<16 | (w) );\ |
| 199 | CmdQueLen--; |
| 200 | |
| 201 | #define SiS300SetupPATFG(color) \ |
| 202 | if(CmdQueLen <= 0) SiS300Idle;\ |
| 203 | MMIO_OUT32(ivideo->mmio_vbase, BR(7), color);\ |
| 204 | CmdQueLen--; |
| 205 | |
| 206 | #define SiS300SetupPATBG(color) \ |
| 207 | if(CmdQueLen <= 0) SiS300Idle;\ |
| 208 | MMIO_OUT32(ivideo->mmio_vbase, BR(8), color);\ |
| 209 | CmdQueLen--; |
| 210 | |
| 211 | #define SiS300SetupSRCFG(color) \ |
| 212 | if(CmdQueLen <= 0) SiS300Idle;\ |
| 213 | MMIO_OUT32(ivideo->mmio_vbase, BR(9), color);\ |
| 214 | CmdQueLen--; |
| 215 | |
| 216 | #define SiS300SetupSRCBG(color) \ |
| 217 | if(CmdQueLen <= 0) SiS300Idle;\ |
| 218 | MMIO_OUT32(ivideo->mmio_vbase, BR(10), color);\ |
| 219 | CmdQueLen--; |
| 220 | |
| 221 | /* 0x8224 src colorkey high */ |
| 222 | /* 0x8228 src colorkey low */ |
| 223 | /* 0x821c dest colorkey high */ |
| 224 | /* 0x8220 dest colorkey low */ |
| 225 | #define SiS300SetupSRCTrans(color) \ |
| 226 | if(CmdQueLen <= 1) SiS300Idle;\ |
| 227 | MMIO_OUT32(ivideo->mmio_vbase, 0x8224, color);\ |
| 228 | MMIO_OUT32(ivideo->mmio_vbase, 0x8228, color);\ |
| 229 | CmdQueLen -= 2; |
| 230 | |
| 231 | #define SiS300SetupDSTTrans(color) \ |
| 232 | if(CmdQueLen <= 1) SiS300Idle;\ |
| 233 | MMIO_OUT32(ivideo->mmio_vbase, 0x821C, color); \ |
| 234 | MMIO_OUT32(ivideo->mmio_vbase, 0x8220, color); \ |
| 235 | CmdQueLen -= 2; |
| 236 | |
| 237 | #define SiS300SetupMONOPAT(p0,p1) \ |
| 238 | if(CmdQueLen <= 1) SiS300Idle;\ |
| 239 | MMIO_OUT32(ivideo->mmio_vbase, BR(11), p0);\ |
| 240 | MMIO_OUT32(ivideo->mmio_vbase, BR(12), p1);\ |
| 241 | CmdQueLen -= 2; |
| 242 | |
| 243 | #define SiS300SetupClipLT(left,top) \ |
| 244 | if(CmdQueLen <= 0) SiS300Idle;\ |
| 245 | MMIO_OUT32(ivideo->mmio_vbase, BR(13), ((left) & 0xFFFF) | (top)<<16 );\ |
| 246 | CmdQueLen--; |
| 247 | |
| 248 | #define SiS300SetupClipRB(right,bottom) \ |
| 249 | if(CmdQueLen <= 0) SiS300Idle;\ |
| 250 | MMIO_OUT32(ivideo->mmio_vbase, BR(14), ((right) & 0xFFFF) | (bottom)<<16 );\ |
| 251 | CmdQueLen--; |
| 252 | |
| 253 | /* General */ |
| 254 | #define SiS300SetupROP(rop) \ |
| 255 | ivideo->CommandReg = (rop) << 8; |
| 256 | |
| 257 | #define SiS300SetupCMDFlag(flags) \ |
| 258 | ivideo->CommandReg |= (flags); |
| 259 | |
| 260 | #define SiS300DoCMD \ |
| 261 | if(CmdQueLen <= 1) SiS300Idle;\ |
| 262 | MMIO_OUT32(ivideo->mmio_vbase, BR(15), ivideo->CommandReg); \ |
| 263 | MMIO_OUT32(ivideo->mmio_vbase, BR(16), 0);\ |
| 264 | CmdQueLen -= 2; |
| 265 | |
| 266 | /* -------------- SiS 315/330 series --------------- */ |
| 267 | |
| 268 | /* Q_STATUS: |
| 269 | bit 31 = 1: All engines idle and all queues empty |
| 270 | bit 30 = 1: Hardware Queue (=HW CQ, 2D queue, 3D queue) empty |
| 271 | bit 29 = 1: 2D engine is idle |
| 272 | bit 28 = 1: 3D engine is idle |
| 273 | bit 27 = 1: HW command queue empty |
| 274 | bit 26 = 1: 2D queue empty |
| 275 | bit 25 = 1: 3D queue empty |
| 276 | bit 24 = 1: SW command queue empty |
| 277 | bits 23:16: 2D counter 3 |
| 278 | bits 15:8: 2D counter 2 |
| 279 | bits 7:0: 2D counter 1 |
| 280 | */ |
| 281 | |
| 282 | #define SiS310Idle \ |
| 283 | { \ |
| 284 | while( (MMIO_IN16(ivideo->mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \ |
| 285 | while( (MMIO_IN16(ivideo->mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \ |
| 286 | CmdQueLen = 0; \ |
| 287 | } |
| 288 | |
| 289 | #define SiS310SetupSRCBase(base) \ |
| 290 | if(CmdQueLen <= 0) SiS310Idle;\ |
| 291 | MMIO_OUT32(ivideo->mmio_vbase, SRC_ADDR, base);\ |
| 292 | CmdQueLen--; |
| 293 | |
| 294 | #define SiS310SetupSRCPitch(pitch) \ |
| 295 | if(CmdQueLen <= 0) SiS310Idle;\ |
| 296 | MMIO_OUT16(ivideo->mmio_vbase, SRC_PITCH, pitch);\ |
| 297 | CmdQueLen--; |
| 298 | |
| 299 | #define SiS310SetupSRCXY(x,y) \ |
| 300 | if(CmdQueLen <= 0) SiS310Idle;\ |
| 301 | MMIO_OUT32(ivideo->mmio_vbase, SRC_Y, (x)<<16 | (y) );\ |
| 302 | CmdQueLen--; |
| 303 | |
| 304 | #define SiS310SetupDSTBase(base) \ |
| 305 | if(CmdQueLen <= 0) SiS310Idle;\ |
| 306 | MMIO_OUT32(ivideo->mmio_vbase, DST_ADDR, base);\ |
| 307 | CmdQueLen--; |
| 308 | |
| 309 | #define SiS310SetupDSTXY(x,y) \ |
| 310 | if(CmdQueLen <= 0) SiS310Idle;\ |
| 311 | MMIO_OUT32(ivideo->mmio_vbase, DST_Y, (x)<<16 | (y) );\ |
| 312 | CmdQueLen--; |
| 313 | |
| 314 | #define SiS310SetupDSTRect(x,y) \ |
| 315 | if(CmdQueLen <= 0) SiS310Idle;\ |
| 316 | MMIO_OUT32(ivideo->mmio_vbase, DST_PITCH, (y)<<16 | (x) );\ |
| 317 | CmdQueLen--; |
| 318 | |
| 319 | #define SiS310SetupDSTColorDepth(bpp) \ |
| 320 | if(CmdQueLen <= 0) SiS310Idle;\ |
| 321 | MMIO_OUT16(ivideo->mmio_vbase, AGP_BASE, bpp);\ |
| 322 | CmdQueLen--; |
| 323 | |
| 324 | #define SiS310SetupRect(w,h) \ |
| 325 | if(CmdQueLen <= 0) SiS310Idle;\ |
| 326 | MMIO_OUT32(ivideo->mmio_vbase, RECT_WIDTH, (h)<<16 | (w) );\ |
| 327 | CmdQueLen--; |
| 328 | |
| 329 | #define SiS310SetupPATFG(color) \ |
| 330 | if(CmdQueLen <= 0) SiS310Idle;\ |
| 331 | MMIO_OUT32(ivideo->mmio_vbase, PAT_FGCOLOR, color);\ |
| 332 | CmdQueLen--; |
| 333 | |
| 334 | #define SiS310SetupPATBG(color) \ |
| 335 | if(CmdQueLen <= 0) SiS310Idle;\ |
| 336 | MMIO_OUT32(ivideo->mmio_vbase, PAT_BGCOLOR, color);\ |
| 337 | CmdQueLen--; |
| 338 | |
| 339 | #define SiS310SetupSRCFG(color) \ |
| 340 | if(CmdQueLen <= 0) SiS310Idle;\ |
| 341 | MMIO_OUT32(ivideo->mmio_vbase, SRC_FGCOLOR, color);\ |
| 342 | CmdQueLen--; |
| 343 | |
| 344 | #define SiS310SetupSRCBG(color) \ |
| 345 | if(CmdQueLen <= 0) SiS310Idle;\ |
| 346 | MMIO_OUT32(ivideo->mmio_vbase, SRC_BGCOLOR, color);\ |
| 347 | CmdQueLen--; |
| 348 | |
| 349 | #define SiS310SetupSRCTrans(color) \ |
| 350 | if(CmdQueLen <= 1) SiS310Idle;\ |
| 351 | MMIO_OUT32(ivideo->mmio_vbase, TRANS_SRC_KEY_HIGH, color);\ |
| 352 | MMIO_OUT32(ivideo->mmio_vbase, TRANS_SRC_KEY_LOW, color);\ |
| 353 | CmdQueLen -= 2; |
| 354 | |
| 355 | #define SiS310SetupDSTTrans(color) \ |
| 356 | if(CmdQueLen <= 1) SiS310Idle;\ |
| 357 | MMIO_OUT32(ivideo->mmio_vbase, TRANS_DST_KEY_HIGH, color); \ |
| 358 | MMIO_OUT32(ivideo->mmio_vbase, TRANS_DST_KEY_LOW, color); \ |
| 359 | CmdQueLen -= 2; |
| 360 | |
| 361 | #define SiS310SetupMONOPAT(p0,p1) \ |
| 362 | if(CmdQueLen <= 1) SiS310Idle;\ |
| 363 | MMIO_OUT32(ivideo->mmio_vbase, MONO_MASK, p0);\ |
| 364 | MMIO_OUT32(ivideo->mmio_vbase, MONO_MASK+4, p1);\ |
| 365 | CmdQueLen -= 2; |
| 366 | |
| 367 | #define SiS310SetupClipLT(left,top) \ |
| 368 | if(CmdQueLen <= 0) SiS310Idle;\ |
| 369 | MMIO_OUT32(ivideo->mmio_vbase, LEFT_CLIP, ((left) & 0xFFFF) | (top)<<16 );\ |
| 370 | CmdQueLen--; |
| 371 | |
| 372 | #define SiS310SetupClipRB(right,bottom) \ |
| 373 | if(CmdQueLen <= 0) SiS310Idle;\ |
| 374 | MMIO_OUT32(ivideo->mmio_vbase, RIGHT_CLIP, ((right) & 0xFFFF) | (bottom)<<16 );\ |
| 375 | CmdQueLen--; |
| 376 | |
| 377 | #define SiS310SetupROP(rop) \ |
| 378 | ivideo->CommandReg = (rop) << 8; |
| 379 | |
| 380 | #define SiS310SetupCMDFlag(flags) \ |
| 381 | ivideo->CommandReg |= (flags); |
| 382 | |
| 383 | #define SiS310DoCMD \ |
| 384 | if(CmdQueLen <= 1) SiS310Idle;\ |
| 385 | MMIO_OUT32(ivideo->mmio_vbase, COMMAND_READY, ivideo->CommandReg); \ |
| 386 | MMIO_OUT32(ivideo->mmio_vbase, FIRE_TRIGGER, 0); \ |
| 387 | CmdQueLen -= 2; |
| 388 | |
| 389 | |
| 390 | int sisfb_initaccel(struct sis_video_info *ivideo); |
| 391 | void sisfb_syncaccel(struct sis_video_info *ivideo); |
| 392 | |
| 393 | #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33) |
| 394 | void fbcon_sis_bmove(struct display *p, int srcy, int srcx, int dsty, |
| 395 | int dstx, int height, int width); |
| 396 | void fbcon_sis_revc(struct display *p, int srcy, int srcx); |
| 397 | void fbcon_sis_clear8(struct vc_data *conp, struct display *p, int srcy, |
| 398 | int srcx, int height, int width); |
| 399 | void fbcon_sis_clear16(struct vc_data *conp, struct display *p, int srcy, |
| 400 | int srcx, int height, int width); |
| 401 | void fbcon_sis_clear32(struct vc_data *conp, struct display *p, int srcy, |
| 402 | int srcx, int height, int width); |
| 403 | #endif |
| 404 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34) |
| 405 | void fbcon_sis_fillrect(struct fb_info *info, const struct fb_fillrect *rect); |
| 406 | void fbcon_sis_copyarea(struct fb_info *info, const struct fb_copyarea *area); |
| 407 | #endif |
| 408 | |
| 409 | #endif |