Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.13 678 lines 19 kB view raw
1/* 2 * SiS 300/630/730/540/315/550/65x/74x/330/760 frame buffer driver 3 * for Linux kernels 2.4.x and 2.6.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 XFree86/X.org driver which is 22 * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria 23 * 24 * Author: Thomas Winischhofer <thomas@winischhofer.net> 25 * (see http://www.winischhofer.net/ 26 * for more information and updates) 27 */ 28 29#include <linux/config.h> 30#include <linux/version.h> 31#include <linux/module.h> 32#include <linux/kernel.h> 33#include <linux/errno.h> 34#include <linux/fb.h> 35#include <linux/console.h> 36#include <linux/selection.h> 37#include <linux/ioport.h> 38#include <linux/capability.h> 39#include <linux/fs.h> 40#include <linux/types.h> 41 42#include <asm/io.h> 43 44#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) 45#include <video/fbcon.h> 46#include <video/fbcon-cfb8.h> 47#include <video/fbcon-cfb16.h> 48#include <video/fbcon-cfb24.h> 49#include <video/fbcon-cfb32.h> 50#endif 51 52#include "sis.h" 53#include "sis_accel.h" 54 55static const u8 sisALUConv[] = 56{ 57 0x00, /* dest = 0; 0, GXclear, 0 */ 58 0x88, /* dest &= src; DSa, GXand, 0x1 */ 59 0x44, /* dest = src & ~dest; SDna, GXandReverse, 0x2 */ 60 0xCC, /* dest = src; S, GXcopy, 0x3 */ 61 0x22, /* dest &= ~src; DSna, GXandInverted, 0x4 */ 62 0xAA, /* dest = dest; D, GXnoop, 0x5 */ 63 0x66, /* dest = ^src; DSx, GXxor, 0x6 */ 64 0xEE, /* dest |= src; DSo, GXor, 0x7 */ 65 0x11, /* dest = ~src & ~dest; DSon, GXnor, 0x8 */ 66 0x99, /* dest ^= ~src ; DSxn, GXequiv, 0x9 */ 67 0x55, /* dest = ~dest; Dn, GXInvert, 0xA */ 68 0xDD, /* dest = src|~dest ; SDno, GXorReverse, 0xB */ 69 0x33, /* dest = ~src; Sn, GXcopyInverted, 0xC */ 70 0xBB, /* dest |= ~src; DSno, GXorInverted, 0xD */ 71 0x77, /* dest = ~src|~dest; DSan, GXnand, 0xE */ 72 0xFF, /* dest = 0xFF; 1, GXset, 0xF */ 73}; 74/* same ROP but with Pattern as Source */ 75static const u8 sisPatALUConv[] = 76{ 77 0x00, /* dest = 0; 0, GXclear, 0 */ 78 0xA0, /* dest &= src; DPa, GXand, 0x1 */ 79 0x50, /* dest = src & ~dest; PDna, GXandReverse, 0x2 */ 80 0xF0, /* dest = src; P, GXcopy, 0x3 */ 81 0x0A, /* dest &= ~src; DPna, GXandInverted, 0x4 */ 82 0xAA, /* dest = dest; D, GXnoop, 0x5 */ 83 0x5A, /* dest = ^src; DPx, GXxor, 0x6 */ 84 0xFA, /* dest |= src; DPo, GXor, 0x7 */ 85 0x05, /* dest = ~src & ~dest; DPon, GXnor, 0x8 */ 86 0xA5, /* dest ^= ~src ; DPxn, GXequiv, 0x9 */ 87 0x55, /* dest = ~dest; Dn, GXInvert, 0xA */ 88 0xF5, /* dest = src|~dest ; PDno, GXorReverse, 0xB */ 89 0x0F, /* dest = ~src; Pn, GXcopyInverted, 0xC */ 90 0xAF, /* dest |= ~src; DPno, GXorInverted, 0xD */ 91 0x5F, /* dest = ~src|~dest; DPan, GXnand, 0xE */ 92 0xFF, /* dest = 0xFF; 1, GXset, 0xF */ 93}; 94 95#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34) 96static const int myrops[] = { 97 3, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 98}; 99#endif 100 101/* 300 series ----------------------------------------------------- */ 102#ifdef CONFIG_FB_SIS_300 103static void 104SiS300Sync(struct sis_video_info *ivideo) 105{ 106 SiS300Idle 107} 108 109static void 110SiS300SetupForScreenToScreenCopy(struct sis_video_info *ivideo, int xdir, int ydir, 111 int rop, int trans_color) 112{ 113 SiS300SetupDSTColorDepth(ivideo->DstColor); 114 SiS300SetupSRCPitch(ivideo->video_linelength) 115 SiS300SetupDSTRect(ivideo->video_linelength, 0xffff) 116 117 if(trans_color != -1) { 118 SiS300SetupROP(0x0A) 119 SiS300SetupSRCTrans(trans_color) 120 SiS300SetupCMDFlag(TRANSPARENT_BITBLT) 121 } else { 122 SiS300SetupROP(sisALUConv[rop]) 123 } 124 if(xdir > 0) { 125 SiS300SetupCMDFlag(X_INC) 126 } 127 if(ydir > 0) { 128 SiS300SetupCMDFlag(Y_INC) 129 } 130} 131 132static void 133SiS300SubsequentScreenToScreenCopy(struct sis_video_info *ivideo, int src_x, 134 int src_y, int dst_x, int dst_y, int width, int height) 135{ 136 u32 srcbase = 0, dstbase = 0; 137 138 if(src_y >= 2048) { 139 srcbase = ivideo->video_linelength * src_y; 140 src_y = 0; 141 } 142 if(dst_y >= 2048) { 143 dstbase = ivideo->video_linelength * dst_y; 144 dst_y = 0; 145 } 146 147 SiS300SetupSRCBase(srcbase); 148 SiS300SetupDSTBase(dstbase); 149 150 if(!(ivideo->CommandReg & X_INC)) { 151 src_x += width-1; 152 dst_x += width-1; 153 } 154 if(!(ivideo->CommandReg & Y_INC)) { 155 src_y += height-1; 156 dst_y += height-1; 157 } 158 SiS300SetupRect(width, height) 159 SiS300SetupSRCXY(src_x, src_y) 160 SiS300SetupDSTXY(dst_x, dst_y) 161 SiS300DoCMD 162} 163 164static void 165SiS300SetupForSolidFill(struct sis_video_info *ivideo, u32 color, int rop) 166{ 167 SiS300SetupPATFG(color) 168 SiS300SetupDSTRect(ivideo->video_linelength, 0xffff) 169 SiS300SetupDSTColorDepth(ivideo->DstColor); 170 SiS300SetupROP(sisPatALUConv[rop]) 171 SiS300SetupCMDFlag(PATFG) 172} 173 174static void 175SiS300SubsequentSolidFillRect(struct sis_video_info *ivideo, int x, int y, int w, int h) 176{ 177 u32 dstbase = 0; 178 179 if(y >= 2048) { 180 dstbase = ivideo->video_linelength * y; 181 y = 0; 182 } 183 SiS300SetupDSTBase(dstbase) 184 SiS300SetupDSTXY(x,y) 185 SiS300SetupRect(w,h) 186 SiS300SetupCMDFlag(X_INC | Y_INC | BITBLT) 187 SiS300DoCMD 188} 189#endif 190 191/* 315/330 series ------------------------------------------------- */ 192 193#ifdef CONFIG_FB_SIS_315 194static void 195SiS310Sync(struct sis_video_info *ivideo) 196{ 197 SiS310Idle 198} 199 200static void 201SiS310SetupForScreenToScreenCopy(struct sis_video_info *ivideo, int rop, int trans_color) 202{ 203 SiS310SetupDSTColorDepth(ivideo->DstColor); 204 SiS310SetupSRCPitch(ivideo->video_linelength) 205 SiS310SetupDSTRect(ivideo->video_linelength, 0xffff) 206 if(trans_color != -1) { 207 SiS310SetupROP(0x0A) 208 SiS310SetupSRCTrans(trans_color) 209 SiS310SetupCMDFlag(TRANSPARENT_BITBLT) 210 } else { 211 SiS310SetupROP(sisALUConv[rop]) 212 /* Set command - not needed, both 0 */ 213 /* SiSSetupCMDFlag(BITBLT | SRCVIDEO) */ 214 } 215 SiS310SetupCMDFlag(ivideo->SiS310_AccelDepth) 216 /* The 315 series is smart enough to know the direction */ 217} 218 219static void 220SiS310SubsequentScreenToScreenCopy(struct sis_video_info *ivideo, int src_x, int src_y, 221 int dst_x, int dst_y, int width, int height) 222{ 223 u32 srcbase = 0, dstbase = 0; 224 int mymin = min(src_y, dst_y); 225 int mymax = max(src_y, dst_y); 226 227 /* Although the chip knows the direction to use 228 * if the source and destination areas overlap, 229 * that logic fails if we fiddle with the bitmap 230 * addresses. Therefore, we check if the source 231 * and destination blitting areas overlap and 232 * adapt the bitmap addresses synchronously 233 * if the coordinates exceed the valid range. 234 * The the areas do not overlap, we do our 235 * normal check. 236 */ 237 if((mymax - mymin) < height) { 238 if((src_y >= 2048) || (dst_y >= 2048)) { 239 srcbase = ivideo->video_linelength * mymin; 240 dstbase = ivideo->video_linelength * mymin; 241 src_y -= mymin; 242 dst_y -= mymin; 243 } 244 } else { 245 if(src_y >= 2048) { 246 srcbase = ivideo->video_linelength * src_y; 247 src_y = 0; 248 } 249 if(dst_y >= 2048) { 250 dstbase = ivideo->video_linelength * dst_y; 251 dst_y = 0; 252 } 253 } 254 255 SiS310SetupSRCBase(srcbase); 256 SiS310SetupDSTBase(dstbase); 257 SiS310SetupRect(width, height) 258 SiS310SetupSRCXY(src_x, src_y) 259 SiS310SetupDSTXY(dst_x, dst_y) 260 SiS310DoCMD 261} 262 263static void 264SiS310SetupForSolidFill(struct sis_video_info *ivideo, u32 color, int rop) 265{ 266 SiS310SetupPATFG(color) 267 SiS310SetupDSTRect(ivideo->video_linelength, 0xffff) 268 SiS310SetupDSTColorDepth(ivideo->DstColor); 269 SiS310SetupROP(sisPatALUConv[rop]) 270 SiS310SetupCMDFlag(PATFG | ivideo->SiS310_AccelDepth) 271} 272 273static void 274SiS310SubsequentSolidFillRect(struct sis_video_info *ivideo, int x, int y, int w, int h) 275{ 276 u32 dstbase = 0; 277 278 if(y >= 2048) { 279 dstbase = ivideo->video_linelength * y; 280 y = 0; 281 } 282 SiS310SetupDSTBase(dstbase) 283 SiS310SetupDSTXY(x,y) 284 SiS310SetupRect(w,h) 285 SiS310SetupCMDFlag(BITBLT) 286 SiS310DoCMD 287} 288#endif 289 290/* --------------------------------------------------------------------- */ 291 292/* The exported routines */ 293 294int sisfb_initaccel(struct sis_video_info *ivideo) 295{ 296#ifdef SISFB_USE_SPINLOCKS 297 spin_lock_init(&ivideo->lockaccel); 298#endif 299 return(0); 300} 301 302void sisfb_syncaccel(struct sis_video_info *ivideo) 303{ 304 if(ivideo->sisvga_engine == SIS_300_VGA) { 305#ifdef CONFIG_FB_SIS_300 306 SiS300Sync(ivideo); 307#endif 308 } else { 309#ifdef CONFIG_FB_SIS_315 310 SiS310Sync(ivideo); 311#endif 312 } 313} 314 315#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) /* --------------- 2.5 --------------- */ 316 317int fbcon_sis_sync(struct fb_info *info) 318{ 319 struct sis_video_info *ivideo = (struct sis_video_info *)info->par; 320 CRITFLAGS 321 322 if(!ivideo->accel) 323 return 0; 324 325 if(ivideo->sisvga_engine == SIS_300_VGA) { 326#ifdef CONFIG_FB_SIS_300 327 SiS300Sync(ivideo); 328#endif 329 } else { 330#ifdef CONFIG_FB_SIS_315 331 SiS310Sync(ivideo); 332#endif 333 } 334 CRITEND 335 return 0; 336} 337 338void fbcon_sis_fillrect(struct fb_info *info, const struct fb_fillrect *rect) 339{ 340 struct sis_video_info *ivideo = (struct sis_video_info *)info->par; 341 u32 col = 0; 342 u32 vxres = info->var.xres_virtual; 343 u32 vyres = info->var.yres_virtual; 344 int width, height; 345 CRITFLAGS 346 347 if(info->state != FBINFO_STATE_RUNNING) { 348 return; 349 } 350 351 if(!ivideo->accel) { 352 cfb_fillrect(info, rect); 353 return; 354 } 355 356 if(!rect->width || !rect->height || rect->dx >= vxres || rect->dy >= vyres) { 357 return; 358 } 359 360 /* Clipping */ 361 width = ((rect->dx + rect->width) > vxres) ? (vxres - rect->dx) : rect->width; 362 height = ((rect->dy + rect->height) > vyres) ? (vyres - rect->dy) : rect->height; 363 364 switch(info->var.bits_per_pixel) { 365 case 8: col = rect->color; 366 break; 367 case 16: 368 case 32: col = ((u32 *)(info->pseudo_palette))[rect->color]; 369 break; 370 } 371 372 if(ivideo->sisvga_engine == SIS_300_VGA) { 373#ifdef CONFIG_FB_SIS_300 374 CRITBEGIN 375 SiS300SetupForSolidFill(ivideo, col, myrops[rect->rop]); 376 SiS300SubsequentSolidFillRect(ivideo, rect->dx, rect->dy, width, height); 377 CRITEND 378 SiS300Sync(ivideo); 379#endif 380 } else { 381#ifdef CONFIG_FB_SIS_315 382 CRITBEGIN 383 SiS310SetupForSolidFill(ivideo, col, myrops[rect->rop]); 384 SiS310SubsequentSolidFillRect(ivideo, rect->dx, rect->dy, width, height); 385 CRITEND 386 SiS310Sync(ivideo); 387#endif 388 } 389 390} 391 392void fbcon_sis_copyarea(struct fb_info *info, const struct fb_copyarea *area) 393{ 394 struct sis_video_info *ivideo = (struct sis_video_info *)info->par; 395 u32 vxres = info->var.xres_virtual; 396 u32 vyres = info->var.yres_virtual; 397 int width = area->width; 398 int height = area->height; 399 CRITFLAGS 400 401 if(info->state != FBINFO_STATE_RUNNING) { 402 return; 403 } 404 405 if(!ivideo->accel) { 406 cfb_copyarea(info, area); 407 return; 408 } 409 410 if(!width || !height || 411 area->sx >= vxres || area->sy >= vyres || 412 area->dx >= vxres || area->dy >= vyres) { 413 return; 414 } 415 416 /* Clipping */ 417 if((area->sx + width) > vxres) width = vxres - area->sx; 418 if((area->dx + width) > vxres) width = vxres - area->dx; 419 if((area->sy + height) > vyres) height = vyres - area->sy; 420 if((area->dy + height) > vyres) height = vyres - area->dy; 421 422 if(ivideo->sisvga_engine == SIS_300_VGA) { 423#ifdef CONFIG_FB_SIS_300 424 int xdir, ydir; 425 426 if(area->sx < area->dx) xdir = 0; 427 else xdir = 1; 428 if(area->sy < area->dy) ydir = 0; 429 else ydir = 1; 430 431 CRITBEGIN 432 SiS300SetupForScreenToScreenCopy(ivideo, xdir, ydir, 3, -1); 433 SiS300SubsequentScreenToScreenCopy(ivideo, area->sx, area->sy, area->dx, area->dy, 434 width, height); 435 CRITEND 436 SiS300Sync(ivideo); 437#endif 438 } else { 439#ifdef CONFIG_FB_SIS_315 440 CRITBEGIN 441 SiS310SetupForScreenToScreenCopy(ivideo, 3, -1); 442 SiS310SubsequentScreenToScreenCopy(ivideo, area->sx, area->sy, area->dx, area->dy, 443 width, height); 444 CRITEND 445 SiS310Sync(ivideo); 446#endif 447 } 448} 449 450#endif 451 452#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* -------------- 2.4 --------------- */ 453 454void fbcon_sis_bmove(struct display *p, int srcy, int srcx, 455 int dsty, int dstx, int height, int width) 456{ 457 struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par; 458 459 CRITFLAGS 460 461 if(!ivideo->accel) { 462 switch(ivideo->video_bpp) { 463 case 8: 464#ifdef FBCON_HAS_CFB8 465 fbcon_cfb8_bmove(p, srcy, srcx, dsty, dstx, height, width); 466#endif 467 break; 468 case 16: 469#ifdef FBCON_HAS_CFB16 470 fbcon_cfb16_bmove(p, srcy, srcx, dsty, dstx, height, width); 471#endif 472 break; 473 case 32: 474#ifdef FBCON_HAS_CFB32 475 fbcon_cfb32_bmove(p, srcy, srcx, dsty, dstx, height, width); 476#endif 477 break; 478 } 479 return; 480 } 481 482 srcx *= fontwidth(p); 483 srcy *= fontheight(p); 484 dstx *= fontwidth(p); 485 dsty *= fontheight(p); 486 width *= fontwidth(p); 487 height *= fontheight(p); 488 489 if(ivideo->sisvga_engine == SIS_300_VGA) { 490#ifdef CONFIG_FB_SIS_300 491 int xdir, ydir; 492 493 if(srcx < dstx) xdir = 0; 494 else xdir = 1; 495 if(srcy < dsty) ydir = 0; 496 else ydir = 1; 497 498 CRITBEGIN 499 SiS300SetupForScreenToScreenCopy(ivideo, xdir, ydir, 3, -1); 500 SiS300SubsequentScreenToScreenCopy(ivideo, srcx, srcy, dstx, dsty, width, height); 501 CRITEND 502 SiS300Sync(ivideo); 503#endif 504 } else { 505#ifdef CONFIG_FB_SIS_315 506 CRITBEGIN 507 SiS310SetupForScreenToScreenCopy(ivideo, 3, -1); 508 SiS310SubsequentScreenToScreenCopy(ivideo, srcx, srcy, dstx, dsty, width, height); 509 CRITEND 510 SiS310Sync(ivideo); 511#endif 512 } 513} 514 515static void fbcon_sis_clear(struct vc_data *conp, struct display *p, 516 int srcy, int srcx, int height, int width, int color) 517{ 518 struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par; 519 CRITFLAGS 520 521 srcx *= fontwidth(p); 522 srcy *= fontheight(p); 523 width *= fontwidth(p); 524 height *= fontheight(p); 525 526 if(ivideo->sisvga_engine == SIS_300_VGA) { 527#ifdef CONFIG_FB_SIS_300 528 CRITBEGIN 529 SiS300SetupForSolidFill(ivideo, color, 3); 530 SiS300SubsequentSolidFillRect(ivideo, srcx, srcy, width, height); 531 CRITEND 532 SiS300Sync(ivideo); 533#endif 534 } else { 535#ifdef CONFIG_FB_SIS_315 536 CRITBEGIN 537 SiS310SetupForSolidFill(ivideo, color, 3); 538 SiS310SubsequentSolidFillRect(ivideo, srcx, srcy, width, height); 539 CRITEND 540 SiS310Sync(ivideo); 541#endif 542 } 543} 544 545void fbcon_sis_clear8(struct vc_data *conp, struct display *p, 546 int srcy, int srcx, int height, int width) 547{ 548 struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par; 549 u32 bgx; 550 551 if(!ivideo->accel) { 552#ifdef FBCON_HAS_CFB8 553 fbcon_cfb8_clear(conp, p, srcy, srcx, height, width); 554#endif 555 return; 556 } 557 558 bgx = attr_bgcol_ec(p, conp); 559 fbcon_sis_clear(conp, p, srcy, srcx, height, width, bgx); 560} 561 562void fbcon_sis_clear16(struct vc_data *conp, struct display *p, 563 int srcy, int srcx, int height, int width) 564{ 565 struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par; 566 u32 bgx; 567 568 if(!ivideo->accel) { 569#ifdef FBCON_HAS_CFB16 570 fbcon_cfb16_clear(conp, p, srcy, srcx, height, width); 571#endif 572 return; 573 } 574 575 bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)]; 576 fbcon_sis_clear(conp, p, srcy, srcx, height, width, bgx); 577} 578 579void fbcon_sis_clear32(struct vc_data *conp, struct display *p, 580 int srcy, int srcx, int height, int width) 581{ 582 struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par; 583 u32 bgx; 584 585 if(!ivideo->accel) { 586#ifdef FBCON_HAS_CFB32 587 fbcon_cfb32_clear(conp, p, srcy, srcx, height, width); 588#endif 589 return; 590 } 591 592 bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)]; 593 fbcon_sis_clear(conp, p, srcy, srcx, height, width, bgx); 594} 595 596void fbcon_sis_revc(struct display *p, int srcx, int srcy) 597{ 598 struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par; 599 CRITFLAGS 600 601 if(!ivideo->accel) { 602 switch(ivideo->video_bpp) { 603 case 16: 604#ifdef FBCON_HAS_CFB16 605 fbcon_cfb16_revc(p, srcx, srcy); 606#endif 607 break; 608 case 32: 609#ifdef FBCON_HAS_CFB32 610 fbcon_cfb32_revc(p, srcx, srcy); 611#endif 612 break; 613 } 614 return; 615 } 616 617 srcx *= fontwidth(p); 618 srcy *= fontheight(p); 619 620 if(ivideo->sisvga_engine == SIS_300_VGA) { 621#ifdef CONFIG_FB_SIS_300 622 CRITBEGIN 623 SiS300SetupForSolidFill(ivideo, 0, 0x0a); 624 SiS300SubsequentSolidFillRect(ivideo, srcx, srcy, fontwidth(p), fontheight(p)); 625 CRITEND 626 SiS300Sync(ivideo); 627#endif 628 } else { 629#ifdef CONFIG_FB_SIS_315 630 CRITBEGIN 631 SiS310SetupForSolidFill(ivideo, 0, 0x0a); 632 SiS310SubsequentSolidFillRect(ivideo, srcx, srcy, fontwidth(p), fontheight(p)); 633 CRITEND 634 SiS310Sync(ivideo); 635#endif 636 } 637} 638 639#ifdef FBCON_HAS_CFB8 640struct display_switch fbcon_sis8 = { 641 .setup = fbcon_cfb8_setup, 642 .bmove = fbcon_sis_bmove, 643 .clear = fbcon_sis_clear8, 644 .putc = fbcon_cfb8_putc, 645 .putcs = fbcon_cfb8_putcs, 646 .revc = fbcon_cfb8_revc, 647 .clear_margins = fbcon_cfb8_clear_margins, 648 .fontwidthmask = FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) 649}; 650#endif 651#ifdef FBCON_HAS_CFB16 652struct display_switch fbcon_sis16 = { 653 .setup = fbcon_cfb16_setup, 654 .bmove = fbcon_sis_bmove, 655 .clear = fbcon_sis_clear16, 656 .putc = fbcon_cfb16_putc, 657 .putcs = fbcon_cfb16_putcs, 658 .revc = fbcon_sis_revc, 659 .clear_margins = fbcon_cfb16_clear_margins, 660 .fontwidthmask = FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) 661}; 662#endif 663#ifdef FBCON_HAS_CFB32 664struct display_switch fbcon_sis32 = { 665 .setup = fbcon_cfb32_setup, 666 .bmove = fbcon_sis_bmove, 667 .clear = fbcon_sis_clear32, 668 .putc = fbcon_cfb32_putc, 669 .putcs = fbcon_cfb32_putcs, 670 .revc = fbcon_sis_revc, 671 .clear_margins = fbcon_cfb32_clear_margins, 672 .fontwidthmask = FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) 673}; 674#endif 675 676#endif /* KERNEL VERSION */ 677 678