1/* 2 * SiS 300/540/630[S]/730[S], 3 * SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[GX], 4 * XGI V3XT/V5/V8, Z7 5 * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3 6 * 7 * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria. 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the named License, 12 * or any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA 22 * 23 * Author: Thomas Winischhofer <thomas@winischhofer.net> 24 * 25 * Author of (practically wiped) code base: 26 * SiS (www.sis.com) 27 * Copyright (C) 1999 Silicon Integrated Systems, Inc. 28 * 29 * See http://www.winischhofer.net/ for more information and updates 30 * 31 * Originally based on the VBE 2.0 compliant graphic boards framebuffer driver, 32 * which is (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de> 33 * 34 */ 35 36#include <linux/version.h> 37#include <linux/module.h> 38#include <linux/moduleparam.h> 39#include <linux/kernel.h> 40#include <linux/spinlock.h> 41#include <linux/errno.h> 42#include <linux/string.h> 43#include <linux/mm.h> 44 45#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) 46#include <linux/tty.h> 47#else 48#include <linux/screen_info.h> 49#endif 50 51#include <linux/slab.h> 52#include <linux/fb.h> 53#include <linux/selection.h> 54#include <linux/ioport.h> 55#include <linux/init.h> 56#include <linux/pci.h> 57#include <linux/vmalloc.h> 58#include <linux/capability.h> 59#include <linux/fs.h> 60#include <linux/types.h> 61#include <asm/uaccess.h> 62#include <asm/io.h> 63#ifdef CONFIG_MTRR 64#include <asm/mtrr.h> 65#endif 66 67#include "sis.h" 68#include "sis_main.h" 69 70static void sisfb_handle_command(struct sis_video_info *ivideo, 71 struct sisfb_cmd *sisfb_command); 72 73/* ------------------ Internal helper routines ----------------- */ 74 75static void __init 76sisfb_setdefaultparms(void) 77{ 78 sisfb_off = 0; 79 sisfb_parm_mem = 0; 80 sisfb_accel = -1; 81 sisfb_ypan = -1; 82 sisfb_max = -1; 83 sisfb_userom = -1; 84 sisfb_useoem = -1; 85 sisfb_mode_idx = -1; 86 sisfb_parm_rate = -1; 87 sisfb_crt1off = 0; 88 sisfb_forcecrt1 = -1; 89 sisfb_crt2type = -1; 90 sisfb_crt2flags = 0; 91 sisfb_pdc = 0xff; 92 sisfb_pdca = 0xff; 93 sisfb_scalelcd = -1; 94 sisfb_specialtiming = CUT_NONE; 95 sisfb_lvdshl = -1; 96 sisfb_dstn = 0; 97 sisfb_fstn = 0; 98 sisfb_tvplug = -1; 99 sisfb_tvstd = -1; 100 sisfb_tvxposoffset = 0; 101 sisfb_tvyposoffset = 0; 102 sisfb_nocrt2rate = 0; 103#if !defined(__i386__) && !defined(__x86_64__) 104 sisfb_resetcard = 0; 105 sisfb_videoram = 0; 106#endif 107} 108 109/* ------------- Parameter parsing -------------- */ 110 111static void __devinit 112sisfb_search_vesamode(unsigned int vesamode, bool quiet) 113{ 114 int i = 0, j = 0; 115 116 /* We don't know the hardware specs yet and there is no ivideo */ 117 118 if(vesamode == 0) { 119 if(!quiet) 120 printk(KERN_ERR "sisfb: Invalid mode. Using default.\n"); 121 122 sisfb_mode_idx = DEFAULT_MODE; 123 124 return; 125 } 126 127 vesamode &= 0x1dff; /* Clean VESA mode number from other flags */ 128 129 while(sisbios_mode[i++].mode_no[0] != 0) { 130 if( (sisbios_mode[i-1].vesa_mode_no_1 == vesamode) || 131 (sisbios_mode[i-1].vesa_mode_no_2 == vesamode) ) { 132 if(sisfb_fstn) { 133 if(sisbios_mode[i-1].mode_no[1] == 0x50 || 134 sisbios_mode[i-1].mode_no[1] == 0x56 || 135 sisbios_mode[i-1].mode_no[1] == 0x53) 136 continue; 137 } else { 138 if(sisbios_mode[i-1].mode_no[1] == 0x5a || 139 sisbios_mode[i-1].mode_no[1] == 0x5b) 140 continue; 141 } 142 sisfb_mode_idx = i - 1; 143 j = 1; 144 break; 145 } 146 } 147 if((!j) && !quiet) 148 printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode); 149} 150 151static void __devinit 152sisfb_search_mode(char *name, bool quiet) 153{ 154 unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0; 155 int i = 0; 156 char strbuf[16], strbuf1[20]; 157 char *nameptr = name; 158 159 /* We don't know the hardware specs yet and there is no ivideo */ 160 161 if(name == NULL) { 162 if(!quiet) 163 printk(KERN_ERR "sisfb: Internal error, using default mode.\n"); 164 165 sisfb_mode_idx = DEFAULT_MODE; 166 return; 167 } 168 169 if(!strnicmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) { 170 if(!quiet) 171 printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n"); 172 173 sisfb_mode_idx = DEFAULT_MODE; 174 return; 175 } 176 177 if(strlen(name) <= 19) { 178 strcpy(strbuf1, name); 179 for(i = 0; i < strlen(strbuf1); i++) { 180 if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' '; 181 } 182 183 /* This does some fuzzy mode naming detection */ 184 if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) { 185 if((rate <= 32) || (depth > 32)) { 186 j = rate; rate = depth; depth = j; 187 } 188 sprintf(strbuf, "%ux%ux%u", xres, yres, depth); 189 nameptr = strbuf; 190 sisfb_parm_rate = rate; 191 } else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) { 192 sprintf(strbuf, "%ux%ux%u", xres, yres, depth); 193 nameptr = strbuf; 194 } else { 195 xres = 0; 196 if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) { 197 sprintf(strbuf, "%ux%ux8", xres, yres); 198 nameptr = strbuf; 199 } else { 200 sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet); 201 return; 202 } 203 } 204 } 205 206 i = 0; j = 0; 207 while(sisbios_mode[i].mode_no[0] != 0) { 208 if(!strnicmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) { 209 if(sisfb_fstn) { 210 if(sisbios_mode[i-1].mode_no[1] == 0x50 || 211 sisbios_mode[i-1].mode_no[1] == 0x56 || 212 sisbios_mode[i-1].mode_no[1] == 0x53) 213 continue; 214 } else { 215 if(sisbios_mode[i-1].mode_no[1] == 0x5a || 216 sisbios_mode[i-1].mode_no[1] == 0x5b) 217 continue; 218 } 219 sisfb_mode_idx = i - 1; 220 j = 1; 221 break; 222 } 223 } 224 225 if((!j) && !quiet) 226 printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr); 227} 228 229#ifndef MODULE 230static void __devinit 231sisfb_get_vga_mode_from_kernel(void) 232{ 233#ifdef CONFIG_X86 234 char mymode[32]; 235 int mydepth = screen_info.lfb_depth; 236 237 if(screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) return; 238 239 if( (screen_info.lfb_width >= 320) && (screen_info.lfb_width <= 2048) && 240 (screen_info.lfb_height >= 200) && (screen_info.lfb_height <= 1536) && 241 (mydepth >= 8) && (mydepth <= 32) ) { 242 243 if(mydepth == 24) mydepth = 32; 244 245 sprintf(mymode, "%ux%ux%u", screen_info.lfb_width, 246 screen_info.lfb_height, 247 mydepth); 248 249 printk(KERN_DEBUG 250 "sisfb: Using vga mode %s pre-set by kernel as default\n", 251 mymode); 252 253 sisfb_search_mode(mymode, true); 254 } 255#endif 256 return; 257} 258#endif 259 260static void __init 261sisfb_search_crt2type(const char *name) 262{ 263 int i = 0; 264 265 /* We don't know the hardware specs yet and there is no ivideo */ 266 267 if(name == NULL) return; 268 269 while(sis_crt2type[i].type_no != -1) { 270 if(!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) { 271 sisfb_crt2type = sis_crt2type[i].type_no; 272 sisfb_tvplug = sis_crt2type[i].tvplug_no; 273 sisfb_crt2flags = sis_crt2type[i].flags; 274 break; 275 } 276 i++; 277 } 278 279 sisfb_dstn = (sisfb_crt2flags & FL_550_DSTN) ? 1 : 0; 280 sisfb_fstn = (sisfb_crt2flags & FL_550_FSTN) ? 1 : 0; 281 282 if(sisfb_crt2type < 0) 283 printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name); 284} 285 286static void __init 287sisfb_search_tvstd(const char *name) 288{ 289 int i = 0; 290 291 /* We don't know the hardware specs yet and there is no ivideo */ 292 293 if(name == NULL) 294 return; 295 296 while(sis_tvtype[i].type_no != -1) { 297 if(!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) { 298 sisfb_tvstd = sis_tvtype[i].type_no; 299 break; 300 } 301 i++; 302 } 303} 304 305static void __init 306sisfb_search_specialtiming(const char *name) 307{ 308 int i = 0; 309 bool found = false; 310 311 /* We don't know the hardware specs yet and there is no ivideo */ 312 313 if(name == NULL) 314 return; 315 316 if(!strnicmp(name, "none", 4)) { 317 sisfb_specialtiming = CUT_FORCENONE; 318 printk(KERN_DEBUG "sisfb: Special timing disabled\n"); 319 } else { 320 while(mycustomttable[i].chipID != 0) { 321 if(!strnicmp(name,mycustomttable[i].optionName, 322 strlen(mycustomttable[i].optionName))) { 323 sisfb_specialtiming = mycustomttable[i].SpecialID; 324 found = true; 325 printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n", 326 mycustomttable[i].vendorName, 327 mycustomttable[i].cardName, 328 mycustomttable[i].optionName); 329 break; 330 } 331 i++; 332 } 333 if(!found) { 334 printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:"); 335 printk(KERN_WARNING "\t\"none\" (to disable special timings)\n"); 336 i = 0; 337 while(mycustomttable[i].chipID != 0) { 338 printk(KERN_WARNING "\t\"%s\" (for %s %s)\n", 339 mycustomttable[i].optionName, 340 mycustomttable[i].vendorName, 341 mycustomttable[i].cardName); 342 i++; 343 } 344 } 345 } 346} 347 348/* ----------- Various detection routines ----------- */ 349 350static void __devinit 351sisfb_detect_custom_timing(struct sis_video_info *ivideo) 352{ 353 unsigned char *biosver = NULL; 354 unsigned char *biosdate = NULL; 355 bool footprint; 356 u32 chksum = 0; 357 int i, j; 358 359 if(ivideo->SiS_Pr.UseROM) { 360 biosver = ivideo->SiS_Pr.VirtualRomBase + 0x06; 361 biosdate = ivideo->SiS_Pr.VirtualRomBase + 0x2c; 362 for(i = 0; i < 32768; i++) 363 chksum += ivideo->SiS_Pr.VirtualRomBase[i]; 364 } 365 366 i = 0; 367 do { 368 if( (mycustomttable[i].chipID == ivideo->chip) && 369 ((!strlen(mycustomttable[i].biosversion)) || 370 (ivideo->SiS_Pr.UseROM && 371 (!strncmp(mycustomttable[i].biosversion, biosver, 372 strlen(mycustomttable[i].biosversion))))) && 373 ((!strlen(mycustomttable[i].biosdate)) || 374 (ivideo->SiS_Pr.UseROM && 375 (!strncmp(mycustomttable[i].biosdate, biosdate, 376 strlen(mycustomttable[i].biosdate))))) && 377 ((!mycustomttable[i].bioschksum) || 378 (ivideo->SiS_Pr.UseROM && 379 (mycustomttable[i].bioschksum == chksum))) && 380 (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) && 381 (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) { 382 footprint = true; 383 for(j = 0; j < 5; j++) { 384 if(mycustomttable[i].biosFootprintAddr[j]) { 385 if(ivideo->SiS_Pr.UseROM) { 386 if(ivideo->SiS_Pr.VirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] != 387 mycustomttable[i].biosFootprintData[j]) { 388 footprint = false; 389 } 390 } else 391 footprint = false; 392 } 393 } 394 if(footprint) { 395 ivideo->SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID; 396 printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n", 397 mycustomttable[i].vendorName, 398 mycustomttable[i].cardName); 399 printk(KERN_DEBUG "sisfb: [specialtiming parameter name: %s]\n", 400 mycustomttable[i].optionName); 401 break; 402 } 403 } 404 i++; 405 } while(mycustomttable[i].chipID); 406} 407 408static bool __devinit 409sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer) 410{ 411 int i, j, xres, yres, refresh, index; 412 u32 emodes; 413 414 if(buffer[0] != 0x00 || buffer[1] != 0xff || 415 buffer[2] != 0xff || buffer[3] != 0xff || 416 buffer[4] != 0xff || buffer[5] != 0xff || 417 buffer[6] != 0xff || buffer[7] != 0x00) { 418 printk(KERN_DEBUG "sisfb: Bad EDID header\n"); 419 return false; 420 } 421 422 if(buffer[0x12] != 0x01) { 423 printk(KERN_INFO "sisfb: EDID version %d not supported\n", 424 buffer[0x12]); 425 return false; 426 } 427 428 monitor->feature = buffer[0x18]; 429 430 if(!buffer[0x14] & 0x80) { 431 if(!(buffer[0x14] & 0x08)) { 432 printk(KERN_INFO 433 "sisfb: WARNING: Monitor does not support separate syncs\n"); 434 } 435 } 436 437 if(buffer[0x13] >= 0x01) { 438 /* EDID V1 rev 1 and 2: Search for monitor descriptor 439 * to extract ranges 440 */ 441 j = 0x36; 442 for(i=0; i<4; i++) { 443 if(buffer[j] == 0x00 && buffer[j + 1] == 0x00 && 444 buffer[j + 2] == 0x00 && buffer[j + 3] == 0xfd && 445 buffer[j + 4] == 0x00) { 446 monitor->hmin = buffer[j + 7]; 447 monitor->hmax = buffer[j + 8]; 448 monitor->vmin = buffer[j + 5]; 449 monitor->vmax = buffer[j + 6]; 450 monitor->dclockmax = buffer[j + 9] * 10 * 1000; 451 monitor->datavalid = true; 452 break; 453 } 454 j += 18; 455 } 456 } 457 458 if(!monitor->datavalid) { 459 /* Otherwise: Get a range from the list of supported 460 * Estabished Timings. This is not entirely accurate, 461 * because fixed frequency monitors are not supported 462 * that way. 463 */ 464 monitor->hmin = 65535; monitor->hmax = 0; 465 monitor->vmin = 65535; monitor->vmax = 0; 466 monitor->dclockmax = 0; 467 emodes = buffer[0x23] | (buffer[0x24] << 8) | (buffer[0x25] << 16); 468 for(i = 0; i < 13; i++) { 469 if(emodes & sisfb_ddcsmodes[i].mask) { 470 if(monitor->hmin > sisfb_ddcsmodes[i].h) monitor->hmin = sisfb_ddcsmodes[i].h; 471 if(monitor->hmax < sisfb_ddcsmodes[i].h) monitor->hmax = sisfb_ddcsmodes[i].h + 1; 472 if(monitor->vmin > sisfb_ddcsmodes[i].v) monitor->vmin = sisfb_ddcsmodes[i].v; 473 if(monitor->vmax < sisfb_ddcsmodes[i].v) monitor->vmax = sisfb_ddcsmodes[i].v; 474 if(monitor->dclockmax < sisfb_ddcsmodes[i].d) monitor->dclockmax = sisfb_ddcsmodes[i].d; 475 } 476 } 477 index = 0x26; 478 for(i = 0; i < 8; i++) { 479 xres = (buffer[index] + 31) * 8; 480 switch(buffer[index + 1] & 0xc0) { 481 case 0xc0: yres = (xres * 9) / 16; break; 482 case 0x80: yres = (xres * 4) / 5; break; 483 case 0x40: yres = (xres * 3) / 4; break; 484 default: yres = xres; break; 485 } 486 refresh = (buffer[index + 1] & 0x3f) + 60; 487 if((xres >= 640) && (yres >= 480)) { 488 for(j = 0; j < 8; j++) { 489 if((xres == sisfb_ddcfmodes[j].x) && 490 (yres == sisfb_ddcfmodes[j].y) && 491 (refresh == sisfb_ddcfmodes[j].v)) { 492 if(monitor->hmin > sisfb_ddcfmodes[j].h) monitor->hmin = sisfb_ddcfmodes[j].h; 493 if(monitor->hmax < sisfb_ddcfmodes[j].h) monitor->hmax = sisfb_ddcfmodes[j].h + 1; 494 if(monitor->vmin > sisfb_ddcsmodes[j].v) monitor->vmin = sisfb_ddcsmodes[j].v; 495 if(monitor->vmax < sisfb_ddcsmodes[j].v) monitor->vmax = sisfb_ddcsmodes[j].v; 496 if(monitor->dclockmax < sisfb_ddcsmodes[j].d) monitor->dclockmax = sisfb_ddcsmodes[j].d; 497 } 498 } 499 } 500 index += 2; 501 } 502 if((monitor->hmin <= monitor->hmax) && (monitor->vmin <= monitor->vmax)) { 503 monitor->datavalid = true; 504 } 505 } 506 507 return monitor->datavalid; 508} 509 510static void __devinit 511sisfb_handle_ddc(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, int crtno) 512{ 513 unsigned short temp, i, realcrtno = crtno; 514 unsigned char buffer[256]; 515 516 monitor->datavalid = false; 517 518 if(crtno) { 519 if(ivideo->vbflags & CRT2_LCD) realcrtno = 1; 520 else if(ivideo->vbflags & CRT2_VGA) realcrtno = 2; 521 else return; 522 } 523 524 if((ivideo->sisfb_crt1off) && (!crtno)) 525 return; 526 527 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine, 528 realcrtno, 0, &buffer[0], ivideo->vbflags2); 529 if((!temp) || (temp == 0xffff)) { 530 printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1); 531 return; 532 } else { 533 printk(KERN_INFO "sisfb: CRT%d DDC supported\n", crtno + 1); 534 printk(KERN_INFO "sisfb: CRT%d DDC level: %s%s%s%s\n", 535 crtno + 1, 536 (temp & 0x1a) ? "" : "[none of the supported]", 537 (temp & 0x02) ? "2 " : "", 538 (temp & 0x08) ? "D&P" : "", 539 (temp & 0x10) ? "FPDI-2" : ""); 540 if(temp & 0x02) { 541 i = 3; /* Number of retrys */ 542 do { 543 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine, 544 realcrtno, 1, &buffer[0], ivideo->vbflags2); 545 } while((temp) && i--); 546 if(!temp) { 547 if(sisfb_interpret_edid(monitor, &buffer[0])) { 548 printk(KERN_INFO "sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n", 549 monitor->hmin, monitor->hmax, monitor->vmin, monitor->vmax, 550 monitor->dclockmax / 1000); 551 } else { 552 printk(KERN_INFO "sisfb: CRT%d DDC EDID corrupt\n", crtno + 1); 553 } 554 } else { 555 printk(KERN_INFO "sisfb: CRT%d DDC reading failed\n", crtno + 1); 556 } 557 } else { 558 printk(KERN_INFO "sisfb: VESA D&P and FPDI-2 not supported yet\n"); 559 } 560 } 561} 562 563/* -------------- Mode validation --------------- */ 564 565static bool 566sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, 567 int mode_idx, int rate_idx, int rate) 568{ 569 int htotal, vtotal; 570 unsigned int dclock, hsync; 571 572 if(!monitor->datavalid) 573 return true; 574 575 if(mode_idx < 0) 576 return false; 577 578 /* Skip for 320x200, 320x240, 640x400 */ 579 switch(sisbios_mode[mode_idx].mode_no[ivideo->mni]) { 580 case 0x59: 581 case 0x41: 582 case 0x4f: 583 case 0x50: 584 case 0x56: 585 case 0x53: 586 case 0x2f: 587 case 0x5d: 588 case 0x5e: 589 return true; 590#ifdef CONFIG_FB_SIS_315 591 case 0x5a: 592 case 0x5b: 593 if(ivideo->sisvga_engine == SIS_315_VGA) return true; 594#endif 595 } 596 597 if(rate < (monitor->vmin - 1)) 598 return false; 599 if(rate > (monitor->vmax + 1)) 600 return false; 601 602 if(sisfb_gettotalfrommode(&ivideo->SiS_Pr, 603 sisbios_mode[mode_idx].mode_no[ivideo->mni], 604 &htotal, &vtotal, rate_idx)) { 605 dclock = (htotal * vtotal * rate) / 1000; 606 if(dclock > (monitor->dclockmax + 1000)) 607 return false; 608 hsync = dclock / htotal; 609 if(hsync < (monitor->hmin - 1)) 610 return false; 611 if(hsync > (monitor->hmax + 1)) 612 return false; 613 } else { 614 return false; 615 } 616 return true; 617} 618 619static int 620sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags) 621{ 622 u16 xres=0, yres, myres; 623 624#ifdef CONFIG_FB_SIS_300 625 if(ivideo->sisvga_engine == SIS_300_VGA) { 626 if(!(sisbios_mode[myindex].chipset & MD_SIS300)) 627 return -1 ; 628 } 629#endif 630#ifdef CONFIG_FB_SIS_315 631 if(ivideo->sisvga_engine == SIS_315_VGA) { 632 if(!(sisbios_mode[myindex].chipset & MD_SIS315)) 633 return -1; 634 } 635#endif 636 637 myres = sisbios_mode[myindex].yres; 638 639 switch(vbflags & VB_DISPTYPE_DISP2) { 640 641 case CRT2_LCD: 642 xres = ivideo->lcdxres; yres = ivideo->lcdyres; 643 644 if((ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) && 645 (ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL856)) { 646 if(sisbios_mode[myindex].xres > xres) 647 return -1; 648 if(myres > yres) 649 return -1; 650 } 651 652 if(ivideo->sisfb_fstn) { 653 if(sisbios_mode[myindex].xres == 320) { 654 if(myres == 240) { 655 switch(sisbios_mode[myindex].mode_no[1]) { 656 case 0x50: myindex = MODE_FSTN_8; break; 657 case 0x56: myindex = MODE_FSTN_16; break; 658 case 0x53: return -1; 659 } 660 } 661 } 662 } 663 664 if(SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres, 665 sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn, 666 ivideo->SiS_Pr.SiS_CustomT, xres, yres, ivideo->vbflags2) < 0x14) { 667 return -1; 668 } 669 break; 670 671 case CRT2_TV: 672 if(SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres, 673 sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) { 674 return -1; 675 } 676 break; 677 678 case CRT2_VGA: 679 if(SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres, 680 sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) { 681 return -1; 682 } 683 break; 684 } 685 686 return myindex; 687} 688 689static u8 690sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int mode_idx) 691{ 692 int i = 0; 693 u16 xres = sisbios_mode[mode_idx].xres; 694 u16 yres = sisbios_mode[mode_idx].yres; 695 696 ivideo->rate_idx = 0; 697 while((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) { 698 if((sisfb_vrate[i].xres == xres) && (sisfb_vrate[i].yres == yres)) { 699 if(sisfb_vrate[i].refresh == rate) { 700 ivideo->rate_idx = sisfb_vrate[i].idx; 701 break; 702 } else if(sisfb_vrate[i].refresh > rate) { 703 if((sisfb_vrate[i].refresh - rate) <= 3) { 704 DPRINTK("sisfb: Adjusting rate from %d up to %d\n", 705 rate, sisfb_vrate[i].refresh); 706 ivideo->rate_idx = sisfb_vrate[i].idx; 707 ivideo->refresh_rate = sisfb_vrate[i].refresh; 708 } else if(((rate - sisfb_vrate[i-1].refresh) <= 2) 709 && (sisfb_vrate[i].idx != 1)) { 710 DPRINTK("sisfb: Adjusting rate from %d down to %d\n", 711 rate, sisfb_vrate[i-1].refresh); 712 ivideo->rate_idx = sisfb_vrate[i-1].idx; 713 ivideo->refresh_rate = sisfb_vrate[i-1].refresh; 714 } 715 break; 716 } else if((rate - sisfb_vrate[i].refresh) <= 2) { 717 DPRINTK("sisfb: Adjusting rate from %d down to %d\n", 718 rate, sisfb_vrate[i].refresh); 719 ivideo->rate_idx = sisfb_vrate[i].idx; 720 break; 721 } 722 } 723 i++; 724 } 725 if(ivideo->rate_idx > 0) { 726 return ivideo->rate_idx; 727 } else { 728 printk(KERN_INFO "sisfb: Unsupported rate %d for %dx%d\n", 729 rate, xres, yres); 730 return 0; 731 } 732} 733 734static bool 735sisfb_bridgeisslave(struct sis_video_info *ivideo) 736{ 737 unsigned char P1_00; 738 739 if(!(ivideo->vbflags2 & VB2_VIDEOBRIDGE)) 740 return false; 741 742 inSISIDXREG(SISPART1,0x00,P1_00); 743 if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) || 744 ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) { 745 return true; 746 } else { 747 return false; 748 } 749} 750 751static bool 752sisfballowretracecrt1(struct sis_video_info *ivideo) 753{ 754 u8 temp; 755 756 inSISIDXREG(SISCR,0x17,temp); 757 if(!(temp & 0x80)) 758 return false; 759 760 inSISIDXREG(SISSR,0x1f,temp); 761 if(temp & 0xc0) 762 return false; 763 764 return true; 765} 766 767static bool 768sisfbcheckvretracecrt1(struct sis_video_info *ivideo) 769{ 770 if(!sisfballowretracecrt1(ivideo)) 771 return false; 772 773 if(inSISREG(SISINPSTAT) & 0x08) 774 return true; 775 else 776 return false; 777} 778 779static void 780sisfbwaitretracecrt1(struct sis_video_info *ivideo) 781{ 782 int watchdog; 783 784 if(!sisfballowretracecrt1(ivideo)) 785 return; 786 787 watchdog = 65536; 788 while((!(inSISREG(SISINPSTAT) & 0x08)) && --watchdog); 789 watchdog = 65536; 790 while((inSISREG(SISINPSTAT) & 0x08) && --watchdog); 791} 792 793static bool 794sisfbcheckvretracecrt2(struct sis_video_info *ivideo) 795{ 796 unsigned char temp, reg; 797 798 switch(ivideo->sisvga_engine) { 799 case SIS_300_VGA: reg = 0x25; break; 800 case SIS_315_VGA: reg = 0x30; break; 801 default: return false; 802 } 803 804 inSISIDXREG(SISPART1, reg, temp); 805 if(temp & 0x02) 806 return true; 807 else 808 return false; 809} 810 811static bool 812sisfb_CheckVBRetrace(struct sis_video_info *ivideo) 813{ 814 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) { 815 if(!sisfb_bridgeisslave(ivideo)) { 816 return sisfbcheckvretracecrt2(ivideo); 817 } 818 } 819 return sisfbcheckvretracecrt1(ivideo); 820} 821 822static u32 823sisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount) 824{ 825 u8 idx, reg1, reg2, reg3, reg4; 826 u32 ret = 0; 827 828 (*vcount) = (*hcount) = 0; 829 830 if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!(sisfb_bridgeisslave(ivideo)))) { 831 832 ret |= (FB_VBLANK_HAVE_VSYNC | 833 FB_VBLANK_HAVE_HBLANK | 834 FB_VBLANK_HAVE_VBLANK | 835 FB_VBLANK_HAVE_VCOUNT | 836 FB_VBLANK_HAVE_HCOUNT); 837 switch(ivideo->sisvga_engine) { 838 case SIS_300_VGA: idx = 0x25; break; 839 default: 840 case SIS_315_VGA: idx = 0x30; break; 841 } 842 inSISIDXREG(SISPART1,(idx+0),reg1); /* 30 */ 843 inSISIDXREG(SISPART1,(idx+1),reg2); /* 31 */ 844 inSISIDXREG(SISPART1,(idx+2),reg3); /* 32 */ 845 inSISIDXREG(SISPART1,(idx+3),reg4); /* 33 */ 846 if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING; 847 if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING; 848 if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING; 849 (*vcount) = reg3 | ((reg4 & 0x70) << 4); 850 (*hcount) = reg2 | ((reg4 & 0x0f) << 8); 851 852 } else if(sisfballowretracecrt1(ivideo)) { 853 854 ret |= (FB_VBLANK_HAVE_VSYNC | 855 FB_VBLANK_HAVE_VBLANK | 856 FB_VBLANK_HAVE_VCOUNT | 857 FB_VBLANK_HAVE_HCOUNT); 858 reg1 = inSISREG(SISINPSTAT); 859 if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING; 860 if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING; 861 inSISIDXREG(SISCR,0x20,reg1); 862 inSISIDXREG(SISCR,0x1b,reg1); 863 inSISIDXREG(SISCR,0x1c,reg2); 864 inSISIDXREG(SISCR,0x1d,reg3); 865 (*vcount) = reg2 | ((reg3 & 0x07) << 8); 866 (*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3; 867 } 868 869 return ret; 870} 871 872static int 873sisfb_myblank(struct sis_video_info *ivideo, int blank) 874{ 875 u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13; 876 bool backlight = true; 877 878 switch(blank) { 879 case FB_BLANK_UNBLANK: /* on */ 880 sr01 = 0x00; 881 sr11 = 0x00; 882 sr1f = 0x00; 883 cr63 = 0x00; 884 p2_0 = 0x20; 885 p1_13 = 0x00; 886 backlight = true; 887 break; 888 case FB_BLANK_NORMAL: /* blank */ 889 sr01 = 0x20; 890 sr11 = 0x00; 891 sr1f = 0x00; 892 cr63 = 0x00; 893 p2_0 = 0x20; 894 p1_13 = 0x00; 895 backlight = true; 896 break; 897 case FB_BLANK_VSYNC_SUSPEND: /* no vsync */ 898 sr01 = 0x20; 899 sr11 = 0x08; 900 sr1f = 0x80; 901 cr63 = 0x40; 902 p2_0 = 0x40; 903 p1_13 = 0x80; 904 backlight = false; 905 break; 906 case FB_BLANK_HSYNC_SUSPEND: /* no hsync */ 907 sr01 = 0x20; 908 sr11 = 0x08; 909 sr1f = 0x40; 910 cr63 = 0x40; 911 p2_0 = 0x80; 912 p1_13 = 0x40; 913 backlight = false; 914 break; 915 case FB_BLANK_POWERDOWN: /* off */ 916 sr01 = 0x20; 917 sr11 = 0x08; 918 sr1f = 0xc0; 919 cr63 = 0x40; 920 p2_0 = 0xc0; 921 p1_13 = 0xc0; 922 backlight = false; 923 break; 924 default: 925 return 1; 926 } 927 928 if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) { 929 930 if( (!ivideo->sisfb_thismonitor.datavalid) || 931 ((ivideo->sisfb_thismonitor.datavalid) && 932 (ivideo->sisfb_thismonitor.feature & 0xe0))) { 933 934 if(ivideo->sisvga_engine == SIS_315_VGA) { 935 setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63); 936 } 937 938 if(!(sisfb_bridgeisslave(ivideo))) { 939 setSISIDXREG(SISSR, 0x01, ~0x20, sr01); 940 setSISIDXREG(SISSR, 0x1f, 0x3f, sr1f); 941 } 942 } 943 944 } 945 946 if(ivideo->currentvbflags & CRT2_LCD) { 947 948 if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) { 949 if(backlight) { 950 SiS_SiS30xBLOn(&ivideo->SiS_Pr); 951 } else { 952 SiS_SiS30xBLOff(&ivideo->SiS_Pr); 953 } 954 } else if(ivideo->sisvga_engine == SIS_315_VGA) { 955#ifdef CONFIG_FB_SIS_315 956 if(ivideo->vbflags2 & VB2_CHRONTEL) { 957 if(backlight) { 958 SiS_Chrontel701xBLOn(&ivideo->SiS_Pr); 959 } else { 960 SiS_Chrontel701xBLOff(&ivideo->SiS_Pr); 961 } 962 } 963#endif 964 } 965 966 if(((ivideo->sisvga_engine == SIS_300_VGA) && 967 (ivideo->vbflags2 & (VB2_301|VB2_30xBDH|VB2_LVDS))) || 968 ((ivideo->sisvga_engine == SIS_315_VGA) && 969 ((ivideo->vbflags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS))) { 970 setSISIDXREG(SISSR, 0x11, ~0x0c, sr11); 971 } 972 973 if(ivideo->sisvga_engine == SIS_300_VGA) { 974 if((ivideo->vbflags2 & VB2_30xB) && 975 (!(ivideo->vbflags2 & VB2_30xBDH))) { 976 setSISIDXREG(SISPART1, 0x13, 0x3f, p1_13); 977 } 978 } else if(ivideo->sisvga_engine == SIS_315_VGA) { 979 if((ivideo->vbflags2 & VB2_30xB) && 980 (!(ivideo->vbflags2 & VB2_30xBDH))) { 981 setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0); 982 } 983 } 984 985 } else if(ivideo->currentvbflags & CRT2_VGA) { 986 987 if(ivideo->vbflags2 & VB2_30xB) { 988 setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0); 989 } 990 991 } 992 993 return 0; 994} 995 996/* ------------- Callbacks from init.c/init301.c -------------- */ 997 998#ifdef CONFIG_FB_SIS_300 999unsigned int 1000sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg) 1001{ 1002 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo; 1003 u32 val = 0; 1004 1005 pci_read_config_dword(ivideo->nbridge, reg, &val); 1006 return (unsigned int)val; 1007} 1008 1009void 1010sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg, unsigned int val) 1011{ 1012 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo; 1013 1014 pci_write_config_dword(ivideo->nbridge, reg, (u32)val); 1015} 1016 1017unsigned int 1018sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg) 1019{ 1020 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo; 1021 u32 val = 0; 1022 1023 if(!ivideo->lpcdev) return 0; 1024 1025 pci_read_config_dword(ivideo->lpcdev, reg, &val); 1026 return (unsigned int)val; 1027} 1028#endif 1029 1030#ifdef CONFIG_FB_SIS_315 1031void 1032sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg, unsigned char val) 1033{ 1034 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo; 1035 1036 pci_write_config_byte(ivideo->nbridge, reg, (u8)val); 1037} 1038 1039unsigned int 1040sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg) 1041{ 1042 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo; 1043 u16 val = 0; 1044 1045 if(!ivideo->lpcdev) return 0; 1046 1047 pci_read_config_word(ivideo->lpcdev, reg, &val); 1048 return (unsigned int)val; 1049} 1050#endif 1051 1052/* ----------- FBDev related routines for all series ----------- */ 1053 1054static int 1055sisfb_get_cmap_len(const struct fb_var_screeninfo *var) 1056{ 1057 return (var->bits_per_pixel == 8) ? 256 : 16; 1058} 1059 1060static void 1061sisfb_set_vparms(struct sis_video_info *ivideo) 1062{ 1063 switch(ivideo->video_bpp) { 1064 case 8: 1065 ivideo->DstColor = 0x0000; 1066 ivideo->SiS310_AccelDepth = 0x00000000; 1067 ivideo->video_cmap_len = 256; 1068 break; 1069 case 16: 1070 ivideo->DstColor = 0x8000; 1071 ivideo->SiS310_AccelDepth = 0x00010000; 1072 ivideo->video_cmap_len = 16; 1073 break; 1074 case 32: 1075 ivideo->DstColor = 0xC000; 1076 ivideo->SiS310_AccelDepth = 0x00020000; 1077 ivideo->video_cmap_len = 16; 1078 break; 1079 default: 1080 ivideo->video_cmap_len = 16; 1081 printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo->video_bpp); 1082 ivideo->accel = 0; 1083 } 1084} 1085 1086static int 1087sisfb_calc_maxyres(struct sis_video_info *ivideo, struct fb_var_screeninfo *var) 1088{ 1089 int maxyres = ivideo->sisfb_mem / (var->xres_virtual * (var->bits_per_pixel >> 3)); 1090 1091 if(maxyres > 32767) maxyres = 32767; 1092 1093 return maxyres; 1094} 1095 1096static void 1097sisfb_calc_pitch(struct sis_video_info *ivideo, struct fb_var_screeninfo *var) 1098{ 1099 ivideo->video_linelength = var->xres_virtual * (var->bits_per_pixel >> 3); 1100 ivideo->scrnpitchCRT1 = ivideo->video_linelength; 1101 if(!(ivideo->currentvbflags & CRT1_LCDA)) { 1102 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { 1103 ivideo->scrnpitchCRT1 <<= 1; 1104 } 1105 } 1106} 1107 1108static void 1109sisfb_set_pitch(struct sis_video_info *ivideo) 1110{ 1111 bool isslavemode = false; 1112 unsigned short HDisplay1 = ivideo->scrnpitchCRT1 >> 3; 1113 unsigned short HDisplay2 = ivideo->video_linelength >> 3; 1114 1115 if(sisfb_bridgeisslave(ivideo)) isslavemode = true; 1116 1117 /* We need to set pitch for CRT1 if bridge is in slave mode, too */ 1118 if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) { 1119 outSISIDXREG(SISCR,0x13,(HDisplay1 & 0xFF)); 1120 setSISIDXREG(SISSR,0x0E,0xF0,(HDisplay1 >> 8)); 1121 } 1122 1123 /* We must not set the pitch for CRT2 if bridge is in slave mode */ 1124 if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) { 1125 orSISIDXREG(SISPART1,ivideo->CRT2_write_enable,0x01); 1126 outSISIDXREG(SISPART1,0x07,(HDisplay2 & 0xFF)); 1127 setSISIDXREG(SISPART1,0x09,0xF0,(HDisplay2 >> 8)); 1128 } 1129} 1130 1131static void 1132sisfb_bpp_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var) 1133{ 1134 ivideo->video_cmap_len = sisfb_get_cmap_len(var); 1135 1136 switch(var->bits_per_pixel) { 1137 case 8: 1138 var->red.offset = var->green.offset = var->blue.offset = 0; 1139 var->red.length = var->green.length = var->blue.length = 6; 1140 break; 1141 case 16: 1142 var->red.offset = 11; 1143 var->red.length = 5; 1144 var->green.offset = 5; 1145 var->green.length = 6; 1146 var->blue.offset = 0; 1147 var->blue.length = 5; 1148 var->transp.offset = 0; 1149 var->transp.length = 0; 1150 break; 1151 case 32: 1152 var->red.offset = 16; 1153 var->red.length = 8; 1154 var->green.offset = 8; 1155 var->green.length = 8; 1156 var->blue.offset = 0; 1157 var->blue.length = 8; 1158 var->transp.offset = 24; 1159 var->transp.length = 8; 1160 break; 1161 } 1162} 1163 1164static int 1165sisfb_set_mode(struct sis_video_info *ivideo, int clrscrn) 1166{ 1167 unsigned short modeno = ivideo->mode_no; 1168 1169 /* >=2.6.12's fbcon clears the screen anyway */ 1170#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12) 1171 if(!clrscrn) modeno |= 0x80; 1172#else 1173 modeno |= 0x80; 1174#endif 1175 1176 outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD); 1177 1178 sisfb_pre_setmode(ivideo); 1179 1180 if(!SiSSetMode(&ivideo->SiS_Pr, modeno)) { 1181 printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no); 1182 return -EINVAL; 1183 } 1184 1185 outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD); 1186 1187 sisfb_post_setmode(ivideo); 1188 1189 return 0; 1190} 1191 1192 1193static int 1194sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *info) 1195{ 1196 struct sis_video_info *ivideo = (struct sis_video_info *)info->par; 1197 unsigned int htotal = 0, vtotal = 0; 1198 unsigned int drate = 0, hrate = 0; 1199 int found_mode = 0, ret; 1200 int old_mode; 1201 u32 pixclock; 1202 1203 htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len; 1204 1205 vtotal = var->upper_margin + var->lower_margin + var->vsync_len; 1206 1207 pixclock = var->pixclock; 1208 1209 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) { 1210 vtotal += var->yres; 1211 vtotal <<= 1; 1212 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) { 1213 vtotal += var->yres; 1214 vtotal <<= 2; 1215 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { 1216 vtotal += var->yres; 1217 vtotal <<= 1; 1218 } else vtotal += var->yres; 1219 1220 if(!(htotal) || !(vtotal)) { 1221 DPRINTK("sisfb: Invalid 'var' information\n"); 1222 return -EINVAL; 1223 } 1224 1225 if(pixclock && htotal && vtotal) { 1226 drate = 1000000000 / pixclock; 1227 hrate = (drate * 1000) / htotal; 1228 ivideo->refresh_rate = (unsigned int) (hrate * 2 / vtotal); 1229 } else { 1230 ivideo->refresh_rate = 60; 1231 } 1232 1233 old_mode = ivideo->sisfb_mode_idx; 1234 ivideo->sisfb_mode_idx = 0; 1235 1236 while( (sisbios_mode[ivideo->sisfb_mode_idx].mode_no[0] != 0) && 1237 (sisbios_mode[ivideo->sisfb_mode_idx].xres <= var->xres) ) { 1238 if( (sisbios_mode[ivideo->sisfb_mode_idx].xres == var->xres) && 1239 (sisbios_mode[ivideo->sisfb_mode_idx].yres == var->yres) && 1240 (sisbios_mode[ivideo->sisfb_mode_idx].bpp == var->bits_per_pixel)) { 1241 ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]; 1242 found_mode = 1; 1243 break; 1244 } 1245 ivideo->sisfb_mode_idx++; 1246 } 1247 1248 if(found_mode) { 1249 ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo, 1250 ivideo->sisfb_mode_idx, ivideo->currentvbflags); 1251 ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]; 1252 } else { 1253 ivideo->sisfb_mode_idx = -1; 1254 } 1255 1256 if(ivideo->sisfb_mode_idx < 0) { 1257 printk(KERN_ERR "sisfb: Mode %dx%dx%d not supported\n", var->xres, 1258 var->yres, var->bits_per_pixel); 1259 ivideo->sisfb_mode_idx = old_mode; 1260 return -EINVAL; 1261 } 1262 1263 if(sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx) == 0) { 1264 ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx; 1265 ivideo->refresh_rate = 60; 1266 } 1267 1268 if(isactive) { 1269 /* If acceleration to be used? Need to know 1270 * before pre/post_set_mode() 1271 */ 1272 ivideo->accel = 0; 1273#if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN) 1274#ifdef STUPID_ACCELF_TEXT_SHIT 1275 if(var->accel_flags & FB_ACCELF_TEXT) { 1276 info->flags &= ~FBINFO_HWACCEL_DISABLED; 1277 } else { 1278 info->flags |= FBINFO_HWACCEL_DISABLED; 1279 } 1280#endif 1281 if(!(info->flags & FBINFO_HWACCEL_DISABLED)) ivideo->accel = -1; 1282#else 1283 if(var->accel_flags & FB_ACCELF_TEXT) ivideo->accel = -1; 1284#endif 1285 1286 if((ret = sisfb_set_mode(ivideo, 1))) { 1287 return ret; 1288 } 1289 1290 ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp; 1291 ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres; 1292 ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres; 1293 1294 sisfb_calc_pitch(ivideo, var); 1295 sisfb_set_pitch(ivideo); 1296 1297 sisfb_set_vparms(ivideo); 1298 1299 ivideo->current_width = ivideo->video_width; 1300 ivideo->current_height = ivideo->video_height; 1301 ivideo->current_bpp = ivideo->video_bpp; 1302 ivideo->current_htotal = htotal; 1303 ivideo->current_vtotal = vtotal; 1304 ivideo->current_linelength = ivideo->video_linelength; 1305 ivideo->current_pixclock = var->pixclock; 1306 ivideo->current_refresh_rate = ivideo->refresh_rate; 1307 ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate; 1308 } 1309 1310 return 0; 1311} 1312 1313static void 1314sisfb_set_base_CRT1(struct sis_video_info *ivideo, unsigned int base) 1315{ 1316 outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD); 1317 1318 outSISIDXREG(SISCR, 0x0D, base & 0xFF); 1319 outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF); 1320 outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF); 1321 if(ivideo->sisvga_engine == SIS_315_VGA) { 1322 setSISIDXREG(SISSR, 0x37, 0xFE, (base >> 24) & 0x01); 1323 } 1324} 1325 1326static void 1327sisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base) 1328{ 1329 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) { 1330 orSISIDXREG(SISPART1, ivideo->CRT2_write_enable, 0x01); 1331 outSISIDXREG(SISPART1, 0x06, (base & 0xFF)); 1332 outSISIDXREG(SISPART1, 0x05, ((base >> 8) & 0xFF)); 1333 outSISIDXREG(SISPART1, 0x04, ((base >> 16) & 0xFF)); 1334 if(ivideo->sisvga_engine == SIS_315_VGA) { 1335 setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7); 1336 } 1337 } 1338} 1339 1340static int 1341sisfb_pan_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var) 1342{ 1343 if(var->xoffset > (var->xres_virtual - var->xres)) { 1344 return -EINVAL; 1345 } 1346 if(var->yoffset > (var->yres_virtual - var->yres)) { 1347 return -EINVAL; 1348 } 1349 1350 ivideo->current_base = (var->yoffset * var->xres_virtual) + var->xoffset; 1351 1352 /* calculate base bpp dep. */ 1353 switch(var->bits_per_pixel) { 1354 case 32: 1355 break; 1356 case 16: 1357 ivideo->current_base >>= 1; 1358 break; 1359 case 8: 1360 default: 1361 ivideo->current_base >>= 2; 1362 break; 1363 } 1364 1365 ivideo->current_base += (ivideo->video_offset >> 2); 1366 1367 sisfb_set_base_CRT1(ivideo, ivideo->current_base); 1368 sisfb_set_base_CRT2(ivideo, ivideo->current_base); 1369 1370 return 0; 1371} 1372 1373static int 1374sisfb_open(struct fb_info *info, int user) 1375{ 1376 return 0; 1377} 1378 1379static int 1380sisfb_release(struct fb_info *info, int user) 1381{ 1382 return 0; 1383} 1384 1385static int 1386sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, 1387 unsigned transp, struct fb_info *info) 1388{ 1389 struct sis_video_info *ivideo = (struct sis_video_info *)info->par; 1390 1391 if(regno >= sisfb_get_cmap_len(&info->var)) 1392 return 1; 1393 1394 switch(info->var.bits_per_pixel) { 1395 case 8: 1396 outSISREG(SISDACA, regno); 1397 outSISREG(SISDACD, (red >> 10)); 1398 outSISREG(SISDACD, (green >> 10)); 1399 outSISREG(SISDACD, (blue >> 10)); 1400 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) { 1401 outSISREG(SISDAC2A, regno); 1402 outSISREG(SISDAC2D, (red >> 8)); 1403 outSISREG(SISDAC2D, (green >> 8)); 1404 outSISREG(SISDAC2D, (blue >> 8)); 1405 } 1406 break; 1407 case 16: 1408 ((u32 *)(info->pseudo_palette))[regno] = 1409 (red & 0xf800) | 1410 ((green & 0xfc00) >> 5) | 1411 ((blue & 0xf800) >> 11); 1412 break; 1413 case 32: 1414 red >>= 8; 1415 green >>= 8; 1416 blue >>= 8; 1417 ((u32 *)(info->pseudo_palette))[regno] = 1418 (red << 16) | (green << 8) | (blue); 1419 break; 1420 } 1421 return 0; 1422} 1423 1424static int 1425sisfb_set_par(struct fb_info *info) 1426{ 1427 int err; 1428 1429 if((err = sisfb_do_set_var(&info->var, 1, info))) 1430 return err; 1431 1432#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) 1433 sisfb_get_fix(&info->fix, info->currcon, info); 1434#else 1435 sisfb_get_fix(&info->fix, -1, info); 1436#endif 1437 return 0; 1438} 1439 1440static int 1441sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) 1442{ 1443 struct sis_video_info *ivideo = (struct sis_video_info *)info->par; 1444 unsigned int htotal = 0, vtotal = 0, myrateindex = 0; 1445 unsigned int drate = 0, hrate = 0, maxyres; 1446 int found_mode = 0; 1447 int refresh_rate, search_idx, tidx; 1448 bool recalc_clock = false; 1449 u32 pixclock; 1450 1451 htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len; 1452 1453 vtotal = var->upper_margin + var->lower_margin + var->vsync_len; 1454 1455 pixclock = var->pixclock; 1456 1457 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) { 1458 vtotal += var->yres; 1459 vtotal <<= 1; 1460 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) { 1461 vtotal += var->yres; 1462 vtotal <<= 2; 1463 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { 1464 vtotal += var->yres; 1465 vtotal <<= 1; 1466 } else 1467 vtotal += var->yres; 1468 1469 if(!(htotal) || !(vtotal)) { 1470 SISFAIL("sisfb: no valid timing data"); 1471 } 1472 1473 search_idx = 0; 1474 while( (sisbios_mode[search_idx].mode_no[0] != 0) && 1475 (sisbios_mode[search_idx].xres <= var->xres) ) { 1476 if( (sisbios_mode[search_idx].xres == var->xres) && 1477 (sisbios_mode[search_idx].yres == var->yres) && 1478 (sisbios_mode[search_idx].bpp == var->bits_per_pixel)) { 1479 if((tidx = sisfb_validate_mode(ivideo, search_idx, 1480 ivideo->currentvbflags)) > 0) { 1481 found_mode = 1; 1482 search_idx = tidx; 1483 break; 1484 } 1485 } 1486 search_idx++; 1487 } 1488 1489 if(!found_mode) { 1490 search_idx = 0; 1491 while(sisbios_mode[search_idx].mode_no[0] != 0) { 1492 if( (var->xres <= sisbios_mode[search_idx].xres) && 1493 (var->yres <= sisbios_mode[search_idx].yres) && 1494 (var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) { 1495 if((tidx = sisfb_validate_mode(ivideo,search_idx, 1496 ivideo->currentvbflags)) > 0) { 1497 found_mode = 1; 1498 search_idx = tidx; 1499 break; 1500 } 1501 } 1502 search_idx++; 1503 } 1504 if(found_mode) { 1505 printk(KERN_DEBUG 1506 "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n", 1507 var->xres, var->yres, var->bits_per_pixel, 1508 sisbios_mode[search_idx].xres, 1509 sisbios_mode[search_idx].yres, 1510 var->bits_per_pixel); 1511 var->xres = sisbios_mode[search_idx].xres; 1512 var->yres = sisbios_mode[search_idx].yres; 1513 } else { 1514 printk(KERN_ERR 1515 "sisfb: Failed to find supported mode near %dx%dx%d\n", 1516 var->xres, var->yres, var->bits_per_pixel); 1517 return -EINVAL; 1518 } 1519 } 1520 1521 if( ((ivideo->vbflags2 & VB2_LVDS) || 1522 ((ivideo->vbflags2 & VB2_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) && 1523 (var->bits_per_pixel == 8) ) { 1524 /* Slave modes on LVDS and 301B-DH */ 1525 refresh_rate = 60; 1526 recalc_clock = true; 1527 } else if( (ivideo->current_htotal == htotal) && 1528 (ivideo->current_vtotal == vtotal) && 1529 (ivideo->current_pixclock == pixclock) ) { 1530 /* x=x & y=y & c=c -> assume depth change */ 1531 drate = 1000000000 / pixclock; 1532 hrate = (drate * 1000) / htotal; 1533 refresh_rate = (unsigned int) (hrate * 2 / vtotal); 1534 } else if( ( (ivideo->current_htotal != htotal) || 1535 (ivideo->current_vtotal != vtotal) ) && 1536 (ivideo->current_pixclock == var->pixclock) ) { 1537 /* x!=x | y!=y & c=c -> invalid pixclock */ 1538 if(ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]) { 1539 refresh_rate = 1540 ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]; 1541 } else if(ivideo->sisfb_parm_rate != -1) { 1542 /* Sic, sisfb_parm_rate - want to know originally desired rate here */ 1543 refresh_rate = ivideo->sisfb_parm_rate; 1544 } else { 1545 refresh_rate = 60; 1546 } 1547 recalc_clock = true; 1548 } else if((pixclock) && (htotal) && (vtotal)) { 1549 drate = 1000000000 / pixclock; 1550 hrate = (drate * 1000) / htotal; 1551 refresh_rate = (unsigned int) (hrate * 2 / vtotal); 1552 } else if(ivideo->current_refresh_rate) { 1553 refresh_rate = ivideo->current_refresh_rate; 1554 recalc_clock = true; 1555 } else { 1556 refresh_rate = 60; 1557 recalc_clock = true; 1558 } 1559 1560 myrateindex = sisfb_search_refresh_rate(ivideo, refresh_rate, search_idx); 1561 1562 /* Eventually recalculate timing and clock */ 1563 if(recalc_clock) { 1564 if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx; 1565 var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, 1566 sisbios_mode[search_idx].mode_no[ivideo->mni], 1567 myrateindex)); 1568 sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, 1569 sisbios_mode[search_idx].mode_no[ivideo->mni], 1570 myrateindex, var); 1571 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) { 1572 var->pixclock <<= 1; 1573 } 1574 } 1575 1576 if(ivideo->sisfb_thismonitor.datavalid) { 1577 if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, search_idx, 1578 myrateindex, refresh_rate)) { 1579 printk(KERN_INFO 1580 "sisfb: WARNING: Refresh rate exceeds monitor specs!\n"); 1581 } 1582 } 1583 1584 /* Adapt RGB settings */ 1585 sisfb_bpp_to_var(ivideo, var); 1586 1587 /* Sanity check for offsets */ 1588 if(var->xoffset < 0) var->xoffset = 0; 1589 if(var->yoffset < 0) var->yoffset = 0; 1590 1591 if(var->xres > var->xres_virtual) 1592 var->xres_virtual = var->xres; 1593 1594 if(ivideo->sisfb_ypan) { 1595 maxyres = sisfb_calc_maxyres(ivideo, var); 1596 if(ivideo->sisfb_max) { 1597 var->yres_virtual = maxyres; 1598 } else { 1599 if(var->yres_virtual > maxyres) { 1600 var->yres_virtual = maxyres; 1601 } 1602 } 1603 if(var->yres_virtual <= var->yres) { 1604 var->yres_virtual = var->yres; 1605 } 1606 } else { 1607 if(var->yres != var->yres_virtual) { 1608 var->yres_virtual = var->yres; 1609 } 1610 var->xoffset = 0; 1611 var->yoffset = 0; 1612 } 1613 1614 /* Truncate offsets to maximum if too high */ 1615 if(var->xoffset > var->xres_virtual - var->xres) { 1616 var->xoffset = var->xres_virtual - var->xres - 1; 1617 } 1618 1619 if(var->yoffset > var->yres_virtual - var->yres) { 1620 var->yoffset = var->yres_virtual - var->yres - 1; 1621 } 1622 1623 /* Set everything else to 0 */ 1624 var->red.msb_right = 1625 var->green.msb_right = 1626 var->blue.msb_right = 1627 var->transp.offset = 1628 var->transp.length = 1629 var->transp.msb_right = 0; 1630 1631 return 0; 1632} 1633 1634static int 1635sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info) 1636{ 1637 struct sis_video_info *ivideo = (struct sis_video_info *)info->par; 1638 int err; 1639 1640 if(var->xoffset > (var->xres_virtual - var->xres)) 1641 return -EINVAL; 1642 1643 if(var->yoffset > (var->yres_virtual - var->yres)) 1644 return -EINVAL; 1645 1646 if(var->vmode & FB_VMODE_YWRAP) 1647 return -EINVAL; 1648 1649 if(var->xoffset + info->var.xres > info->var.xres_virtual || 1650 var->yoffset + info->var.yres > info->var.yres_virtual) 1651 return -EINVAL; 1652 1653 if((err = sisfb_pan_var(ivideo, var)) < 0) 1654 return err; 1655 1656 info->var.xoffset = var->xoffset; 1657 info->var.yoffset = var->yoffset; 1658 1659 return 0; 1660} 1661 1662static int 1663sisfb_blank(int blank, struct fb_info *info) 1664{ 1665 struct sis_video_info *ivideo = (struct sis_video_info *)info->par; 1666 1667 return sisfb_myblank(ivideo, blank); 1668} 1669 1670/* ----------- FBDev related routines for all series ---------- */ 1671 1672#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) 1673static int sisfb_ioctl(struct fb_info *info, unsigned int cmd, 1674 unsigned long arg) 1675#else 1676static int sisfb_ioctl(struct inode *inode, struct file *file, 1677 unsigned int cmd, unsigned long arg, 1678 struct fb_info *info) 1679#endif 1680{ 1681 struct sis_video_info *ivideo = (struct sis_video_info *)info->par; 1682 struct sis_memreq sismemreq; 1683 struct fb_vblank sisvbblank; 1684 u32 gpu32 = 0; 1685#ifndef __user 1686#define __user 1687#endif 1688 u32 __user *argp = (u32 __user *)arg; 1689 1690 switch(cmd) { 1691 case FBIO_ALLOC: 1692 if(!capable(CAP_SYS_RAWIO)) 1693 return -EPERM; 1694 1695 if(copy_from_user(&sismemreq, (void __user *)arg, sizeof(sismemreq))) 1696 return -EFAULT; 1697 1698 sis_malloc(&sismemreq); 1699 1700 if(copy_to_user((void __user *)arg, &sismemreq, sizeof(sismemreq))) { 1701 sis_free((u32)sismemreq.offset); 1702 return -EFAULT; 1703 } 1704 break; 1705 1706 case FBIO_FREE: 1707 if(!capable(CAP_SYS_RAWIO)) 1708 return -EPERM; 1709 1710 if(get_user(gpu32, argp)) 1711 return -EFAULT; 1712 1713 sis_free(gpu32); 1714 break; 1715 1716 case FBIOGET_VBLANK: 1717 sisvbblank.count = 0; 1718 sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount); 1719 1720 if(copy_to_user((void __user *)arg, &sisvbblank, sizeof(sisvbblank))) 1721 return -EFAULT; 1722 1723 break; 1724 1725 case SISFB_GET_INFO_SIZE: 1726 return put_user(sizeof(struct sisfb_info), argp); 1727 1728 case SISFB_GET_INFO_OLD: 1729 if(ivideo->warncount++ < 10) 1730 printk(KERN_INFO 1731 "sisfb: Deprecated ioctl call received - update your application!\n"); 1732 case SISFB_GET_INFO: /* For communication with X driver */ 1733 ivideo->sisfb_infoblock.sisfb_id = SISFB_ID; 1734 ivideo->sisfb_infoblock.sisfb_version = VER_MAJOR; 1735 ivideo->sisfb_infoblock.sisfb_revision = VER_MINOR; 1736 ivideo->sisfb_infoblock.sisfb_patchlevel = VER_LEVEL; 1737 ivideo->sisfb_infoblock.chip_id = ivideo->chip_id; 1738 ivideo->sisfb_infoblock.sisfb_pci_vendor = ivideo->chip_vendor; 1739 ivideo->sisfb_infoblock.memory = ivideo->video_size / 1024; 1740 ivideo->sisfb_infoblock.heapstart = ivideo->heapstart / 1024; 1741 if(ivideo->modechanged) { 1742 ivideo->sisfb_infoblock.fbvidmode = ivideo->mode_no; 1743 } else { 1744 ivideo->sisfb_infoblock.fbvidmode = ivideo->modeprechange; 1745 } 1746 ivideo->sisfb_infoblock.sisfb_caps = ivideo->caps; 1747 ivideo->sisfb_infoblock.sisfb_tqlen = ivideo->cmdQueueSize / 1024; 1748 ivideo->sisfb_infoblock.sisfb_pcibus = ivideo->pcibus; 1749 ivideo->sisfb_infoblock.sisfb_pcislot = ivideo->pcislot; 1750 ivideo->sisfb_infoblock.sisfb_pcifunc = ivideo->pcifunc; 1751 ivideo->sisfb_infoblock.sisfb_lcdpdc = ivideo->detectedpdc; 1752 ivideo->sisfb_infoblock.sisfb_lcdpdca = ivideo->detectedpdca; 1753 ivideo->sisfb_infoblock.sisfb_lcda = ivideo->detectedlcda; 1754 ivideo->sisfb_infoblock.sisfb_vbflags = ivideo->vbflags; 1755 ivideo->sisfb_infoblock.sisfb_currentvbflags = ivideo->currentvbflags; 1756 ivideo->sisfb_infoblock.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler; 1757 ivideo->sisfb_infoblock.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT; 1758 ivideo->sisfb_infoblock.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0; 1759 ivideo->sisfb_infoblock.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0; 1760 ivideo->sisfb_infoblock.sisfb_emi30 = ivideo->SiS_Pr.EMI_30; 1761 ivideo->sisfb_infoblock.sisfb_emi31 = ivideo->SiS_Pr.EMI_31; 1762 ivideo->sisfb_infoblock.sisfb_emi32 = ivideo->SiS_Pr.EMI_32; 1763 ivideo->sisfb_infoblock.sisfb_emi33 = ivideo->SiS_Pr.EMI_33; 1764 ivideo->sisfb_infoblock.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32); 1765 ivideo->sisfb_infoblock.sisfb_tvypos = (u16)(ivideo->tvypos + 32); 1766 ivideo->sisfb_infoblock.sisfb_heapsize = ivideo->sisfb_heap_size / 1024; 1767 ivideo->sisfb_infoblock.sisfb_videooffset = ivideo->video_offset; 1768 ivideo->sisfb_infoblock.sisfb_curfstn = ivideo->curFSTN; 1769 ivideo->sisfb_infoblock.sisfb_curdstn = ivideo->curDSTN; 1770 ivideo->sisfb_infoblock.sisfb_vbflags2 = ivideo->vbflags2; 1771 ivideo->sisfb_infoblock.sisfb_can_post = ivideo->sisfb_can_post ? 1 : 0; 1772 ivideo->sisfb_infoblock.sisfb_card_posted = ivideo->sisfb_card_posted ? 1 : 0; 1773 ivideo->sisfb_infoblock.sisfb_was_boot_device = ivideo->sisfb_was_boot_device ? 1 : 0; 1774 1775 if(copy_to_user((void __user *)arg, &ivideo->sisfb_infoblock, 1776 sizeof(ivideo->sisfb_infoblock))) 1777 return -EFAULT; 1778 1779 break; 1780 1781 case SISFB_GET_VBRSTATUS_OLD: 1782 if(ivideo->warncount++ < 10) 1783 printk(KERN_INFO 1784 "sisfb: Deprecated ioctl call received - update your application!\n"); 1785 case SISFB_GET_VBRSTATUS: 1786 if(sisfb_CheckVBRetrace(ivideo)) 1787 return put_user((u32)1, argp); 1788 else 1789 return put_user((u32)0, argp); 1790 1791 case SISFB_GET_AUTOMAXIMIZE_OLD: 1792 if(ivideo->warncount++ < 10) 1793 printk(KERN_INFO 1794 "sisfb: Deprecated ioctl call received - update your application!\n"); 1795 case SISFB_GET_AUTOMAXIMIZE: 1796 if(ivideo->sisfb_max) 1797 return put_user((u32)1, argp); 1798 else 1799 return put_user((u32)0, argp); 1800 1801 case SISFB_SET_AUTOMAXIMIZE_OLD: 1802 if(ivideo->warncount++ < 10) 1803 printk(KERN_INFO 1804 "sisfb: Deprecated ioctl call received - update your application!\n"); 1805 case SISFB_SET_AUTOMAXIMIZE: 1806 if(get_user(gpu32, argp)) 1807 return -EFAULT; 1808 1809 ivideo->sisfb_max = (gpu32) ? 1 : 0; 1810 break; 1811 1812 case SISFB_SET_TVPOSOFFSET: 1813 if(get_user(gpu32, argp)) 1814 return -EFAULT; 1815 1816 sisfb_set_TVxposoffset(ivideo, ((int)(gpu32 >> 16)) - 32); 1817 sisfb_set_TVyposoffset(ivideo, ((int)(gpu32 & 0xffff)) - 32); 1818 break; 1819 1820 case SISFB_GET_TVPOSOFFSET: 1821 return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)), 1822 argp); 1823 1824 case SISFB_COMMAND: 1825 if(copy_from_user(&ivideo->sisfb_command, (void __user *)arg, 1826 sizeof(struct sisfb_cmd))) 1827 return -EFAULT; 1828 1829 sisfb_handle_command(ivideo, &ivideo->sisfb_command); 1830 1831 if(copy_to_user((void __user *)arg, &ivideo->sisfb_command, 1832 sizeof(struct sisfb_cmd))) 1833 return -EFAULT; 1834 1835 break; 1836 1837 case SISFB_SET_LOCK: 1838 if(get_user(gpu32, argp)) 1839 return -EFAULT; 1840 1841 ivideo->sisfblocked = (gpu32) ? 1 : 0; 1842 break; 1843 1844 default: 1845#ifdef SIS_NEW_CONFIG_COMPAT 1846 return -ENOIOCTLCMD; 1847#else 1848 return -EINVAL; 1849#endif 1850 } 1851 return 0; 1852} 1853 1854static int 1855sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info) 1856{ 1857 struct sis_video_info *ivideo = (struct sis_video_info *)info->par; 1858 1859 memset(fix, 0, sizeof(struct fb_fix_screeninfo)); 1860 1861 strcpy(fix->id, ivideo->myid); 1862 1863 fix->smem_start = ivideo->video_base + ivideo->video_offset; 1864 fix->smem_len = ivideo->sisfb_mem; 1865 fix->type = FB_TYPE_PACKED_PIXELS; 1866 fix->type_aux = 0; 1867 fix->visual = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; 1868 fix->xpanstep = 1; 1869 fix->ypanstep = (ivideo->sisfb_ypan) ? 1 : 0; 1870 fix->ywrapstep = 0; 1871 fix->line_length = ivideo->video_linelength; 1872 fix->mmio_start = ivideo->mmio_base; 1873 fix->mmio_len = ivideo->mmio_size; 1874 if(ivideo->sisvga_engine == SIS_300_VGA) { 1875 fix->accel = FB_ACCEL_SIS_GLAMOUR; 1876 } else if((ivideo->chip == SIS_330) || 1877 (ivideo->chip == SIS_760) || 1878 (ivideo->chip == SIS_761)) { 1879 fix->accel = FB_ACCEL_SIS_XABRE; 1880 } else if(ivideo->chip == XGI_20) { 1881 fix->accel = FB_ACCEL_XGI_VOLARI_Z; 1882 } else if(ivideo->chip >= XGI_40) { 1883 fix->accel = FB_ACCEL_XGI_VOLARI_V; 1884 } else { 1885 fix->accel = FB_ACCEL_SIS_GLAMOUR_2; 1886 } 1887 1888 return 0; 1889} 1890 1891/* ---------------- fb_ops structures ----------------- */ 1892 1893static struct fb_ops sisfb_ops = { 1894 .owner = THIS_MODULE, 1895 .fb_open = sisfb_open, 1896 .fb_release = sisfb_release, 1897 .fb_check_var = sisfb_check_var, 1898 .fb_set_par = sisfb_set_par, 1899 .fb_setcolreg = sisfb_setcolreg, 1900 .fb_pan_display = sisfb_pan_display, 1901 .fb_blank = sisfb_blank, 1902 .fb_fillrect = fbcon_sis_fillrect, 1903 .fb_copyarea = fbcon_sis_copyarea, 1904 .fb_imageblit = cfb_imageblit, 1905#ifdef CONFIG_FB_SOFT_CURSOR 1906 .fb_cursor = soft_cursor, 1907#endif 1908 .fb_sync = fbcon_sis_sync, 1909#ifdef SIS_NEW_CONFIG_COMPAT 1910 .fb_compat_ioctl= sisfb_ioctl, 1911#endif 1912 .fb_ioctl = sisfb_ioctl 1913}; 1914 1915/* ---------------- Chip generation dependent routines ---------------- */ 1916 1917static struct pci_dev * __devinit 1918sisfb_get_northbridge(int basechipid) 1919{ 1920 struct pci_dev *pdev = NULL; 1921 int nbridgenum, nbridgeidx, i; 1922 static const unsigned short nbridgeids[] = { 1923 PCI_DEVICE_ID_SI_540, /* for SiS 540 VGA */ 1924 PCI_DEVICE_ID_SI_630, /* for SiS 630/730 VGA */ 1925 PCI_DEVICE_ID_SI_730, 1926 PCI_DEVICE_ID_SI_550, /* for SiS 550 VGA */ 1927 PCI_DEVICE_ID_SI_650, /* for SiS 650/651/740 VGA */ 1928 PCI_DEVICE_ID_SI_651, 1929 PCI_DEVICE_ID_SI_740, 1930 PCI_DEVICE_ID_SI_661, /* for SiS 661/741/660/760/761 VGA */ 1931 PCI_DEVICE_ID_SI_741, 1932 PCI_DEVICE_ID_SI_660, 1933 PCI_DEVICE_ID_SI_760, 1934 PCI_DEVICE_ID_SI_761 1935 }; 1936 1937 switch(basechipid) { 1938#ifdef CONFIG_FB_SIS_300 1939 case SIS_540: nbridgeidx = 0; nbridgenum = 1; break; 1940 case SIS_630: nbridgeidx = 1; nbridgenum = 2; break; 1941#endif 1942#ifdef CONFIG_FB_SIS_315 1943 case SIS_550: nbridgeidx = 3; nbridgenum = 1; break; 1944 case SIS_650: nbridgeidx = 4; nbridgenum = 3; break; 1945 case SIS_660: nbridgeidx = 7; nbridgenum = 5; break; 1946#endif 1947 default: return NULL; 1948 } 1949 for(i = 0; i < nbridgenum; i++) { 1950 if((pdev = pci_get_device(PCI_VENDOR_ID_SI, 1951 nbridgeids[nbridgeidx+i], NULL))) 1952 break; 1953 } 1954 return pdev; 1955} 1956 1957static int __devinit 1958sisfb_get_dram_size(struct sis_video_info *ivideo) 1959{ 1960#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315) 1961 u8 reg; 1962#endif 1963 1964 ivideo->video_size = 0; 1965 ivideo->UMAsize = ivideo->LFBsize = 0; 1966 1967 switch(ivideo->chip) { 1968#ifdef CONFIG_FB_SIS_300 1969 case SIS_300: 1970 inSISIDXREG(SISSR, 0x14, reg); 1971 ivideo->video_size = ((reg & 0x3F) + 1) << 20; 1972 break; 1973 case SIS_540: 1974 case SIS_630: 1975 case SIS_730: 1976 if(!ivideo->nbridge) 1977 return -1; 1978 pci_read_config_byte(ivideo->nbridge, 0x63, ®); 1979 ivideo->video_size = 1 << (((reg & 0x70) >> 4) + 21); 1980 break; 1981#endif 1982#ifdef CONFIG_FB_SIS_315 1983 case SIS_315H: 1984 case SIS_315PRO: 1985 case SIS_315: 1986 inSISIDXREG(SISSR, 0x14, reg); 1987 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20; 1988 switch((reg >> 2) & 0x03) { 1989 case 0x01: 1990 case 0x03: 1991 ivideo->video_size <<= 1; 1992 break; 1993 case 0x02: 1994 ivideo->video_size += (ivideo->video_size/2); 1995 } 1996 break; 1997 case SIS_330: 1998 inSISIDXREG(SISSR, 0x14, reg); 1999 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20; 2000 if(reg & 0x0c) ivideo->video_size <<= 1; 2001 break; 2002 case SIS_550: 2003 case SIS_650: 2004 case SIS_740: 2005 inSISIDXREG(SISSR, 0x14, reg); 2006 ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20; 2007 break; 2008 case SIS_661: 2009 case SIS_741: 2010 inSISIDXREG(SISCR, 0x79, reg); 2011 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20; 2012 break; 2013 case SIS_660: 2014 case SIS_760: 2015 case SIS_761: 2016 inSISIDXREG(SISCR, 0x79, reg); 2017 reg = (reg & 0xf0) >> 4; 2018 if(reg) { 2019 ivideo->video_size = (1 << reg) << 20; 2020 ivideo->UMAsize = ivideo->video_size; 2021 } 2022 inSISIDXREG(SISCR, 0x78, reg); 2023 reg &= 0x30; 2024 if(reg) { 2025 if(reg == 0x10) { 2026 ivideo->LFBsize = (32 << 20); 2027 } else { 2028 ivideo->LFBsize = (64 << 20); 2029 } 2030 ivideo->video_size += ivideo->LFBsize; 2031 } 2032 break; 2033 case SIS_340: 2034 case XGI_20: 2035 case XGI_40: 2036 inSISIDXREG(SISSR, 0x14, reg); 2037 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20; 2038 if(ivideo->chip != XGI_20) { 2039 reg = (reg & 0x0c) >> 2; 2040 if(ivideo->revision_id == 2) { 2041 if(reg & 0x01) reg = 0x02; 2042 else reg = 0x00; 2043 } 2044 if(reg == 0x02) ivideo->video_size <<= 1; 2045 else if(reg == 0x03) ivideo->video_size <<= 2; 2046 } 2047 break; 2048#endif 2049 default: 2050 return -1; 2051 } 2052 return 0; 2053} 2054 2055/* -------------- video bridge device detection --------------- */ 2056 2057static void __devinit 2058sisfb_detect_VB_connect(struct sis_video_info *ivideo) 2059{ 2060 u8 cr32, temp; 2061 2062 /* No CRT2 on XGI Z7 */ 2063 if(ivideo->chip == XGI_20) { 2064 ivideo->sisfb_crt1off = 0; 2065 return; 2066 } 2067 2068#ifdef CONFIG_FB_SIS_300 2069 if(ivideo->sisvga_engine == SIS_300_VGA) { 2070 inSISIDXREG(SISSR, 0x17, temp); 2071 if((temp & 0x0F) && (ivideo->chip != SIS_300)) { 2072 /* PAL/NTSC is stored on SR16 on such machines */ 2073 if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) { 2074 inSISIDXREG(SISSR, 0x16, temp); 2075 if(temp & 0x20) 2076 ivideo->vbflags |= TV_PAL; 2077 else 2078 ivideo->vbflags |= TV_NTSC; 2079 } 2080 } 2081 } 2082#endif 2083 2084 inSISIDXREG(SISCR, 0x32, cr32); 2085 2086 if(cr32 & SIS_CRT1) { 2087 ivideo->sisfb_crt1off = 0; 2088 } else { 2089 ivideo->sisfb_crt1off = (cr32 & 0xDF) ? 1 : 0; 2090 } 2091 2092 ivideo->vbflags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA); 2093 2094 if(cr32 & SIS_VB_TV) ivideo->vbflags |= CRT2_TV; 2095 if(cr32 & SIS_VB_LCD) ivideo->vbflags |= CRT2_LCD; 2096 if(cr32 & SIS_VB_CRT2) ivideo->vbflags |= CRT2_VGA; 2097 2098 /* Check given parms for hardware compatibility. 2099 * (Cannot do this in the search_xx routines since we don't 2100 * know what hardware we are running on then) 2101 */ 2102 2103 if(ivideo->chip != SIS_550) { 2104 ivideo->sisfb_dstn = ivideo->sisfb_fstn = 0; 2105 } 2106 2107 if(ivideo->sisfb_tvplug != -1) { 2108 if( (ivideo->sisvga_engine != SIS_315_VGA) || 2109 (!(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) ) { 2110 if(ivideo->sisfb_tvplug & TV_YPBPR) { 2111 ivideo->sisfb_tvplug = -1; 2112 printk(KERN_ERR "sisfb: YPbPr not supported\n"); 2113 } 2114 } 2115 } 2116 if(ivideo->sisfb_tvplug != -1) { 2117 if( (ivideo->sisvga_engine != SIS_315_VGA) || 2118 (!(ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) ) { 2119 if(ivideo->sisfb_tvplug & TV_HIVISION) { 2120 ivideo->sisfb_tvplug = -1; 2121 printk(KERN_ERR "sisfb: HiVision not supported\n"); 2122 } 2123 } 2124 } 2125 if(ivideo->sisfb_tvstd != -1) { 2126 if( (!(ivideo->vbflags2 & VB2_SISBRIDGE)) && 2127 (!((ivideo->sisvga_engine == SIS_315_VGA) && 2128 (ivideo->vbflags2 & VB2_CHRONTEL))) ) { 2129 if(ivideo->sisfb_tvstd & (TV_PALN | TV_PALN | TV_NTSCJ)) { 2130 ivideo->sisfb_tvstd = -1; 2131 printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n"); 2132 } 2133 } 2134 } 2135 2136 /* Detect/set TV plug & type */ 2137 if(ivideo->sisfb_tvplug != -1) { 2138 ivideo->vbflags |= ivideo->sisfb_tvplug; 2139 } else { 2140 if(cr32 & SIS_VB_YPBPR) ivideo->vbflags |= (TV_YPBPR|TV_YPBPR525I); /* default: 480i */ 2141 else if(cr32 & SIS_VB_HIVISION) ivideo->vbflags |= TV_HIVISION; 2142 else if(cr32 & SIS_VB_SCART) ivideo->vbflags |= TV_SCART; 2143 else { 2144 if(cr32 & SIS_VB_SVIDEO) ivideo->vbflags |= TV_SVIDEO; 2145 if(cr32 & SIS_VB_COMPOSITE) ivideo->vbflags |= TV_AVIDEO; 2146 } 2147 } 2148 2149 if(!(ivideo->vbflags & (TV_YPBPR | TV_HIVISION))) { 2150 if(ivideo->sisfb_tvstd != -1) { 2151 ivideo->vbflags &= ~(TV_NTSC | TV_PAL | TV_PALM | TV_PALN | TV_NTSCJ); 2152 ivideo->vbflags |= ivideo->sisfb_tvstd; 2153 } 2154 if(ivideo->vbflags & TV_SCART) { 2155 ivideo->vbflags &= ~(TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ); 2156 ivideo->vbflags |= TV_PAL; 2157 } 2158 if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) { 2159 if(ivideo->sisvga_engine == SIS_300_VGA) { 2160 inSISIDXREG(SISSR, 0x38, temp); 2161 if(temp & 0x01) ivideo->vbflags |= TV_PAL; 2162 else ivideo->vbflags |= TV_NTSC; 2163 } else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) { 2164 inSISIDXREG(SISSR, 0x38, temp); 2165 if(temp & 0x01) ivideo->vbflags |= TV_PAL; 2166 else ivideo->vbflags |= TV_NTSC; 2167 } else { 2168 inSISIDXREG(SISCR, 0x79, temp); 2169 if(temp & 0x20) ivideo->vbflags |= TV_PAL; 2170 else ivideo->vbflags |= TV_NTSC; 2171 } 2172 } 2173 } 2174 2175 /* Copy forceCRT1 option to CRT1off if option is given */ 2176 if(ivideo->sisfb_forcecrt1 != -1) { 2177 ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1; 2178 } 2179} 2180 2181/* ------------------ Sensing routines ------------------ */ 2182 2183static bool __devinit 2184sisfb_test_DDC1(struct sis_video_info *ivideo) 2185{ 2186 unsigned short old; 2187 int count = 48; 2188 2189 old = SiS_ReadDDC1Bit(&ivideo->SiS_Pr); 2190 do { 2191 if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break; 2192 } while(count--); 2193 return (count != -1); 2194} 2195 2196static void __devinit 2197sisfb_sense_crt1(struct sis_video_info *ivideo) 2198{ 2199 bool mustwait = false; 2200 u8 sr1F, cr17; 2201#ifdef CONFIG_FB_SIS_315 2202 u8 cr63=0; 2203#endif 2204 u16 temp = 0xffff; 2205 int i; 2206 2207 inSISIDXREG(SISSR,0x1F,sr1F); 2208 orSISIDXREG(SISSR,0x1F,0x04); 2209 andSISIDXREG(SISSR,0x1F,0x3F); 2210 if(sr1F & 0xc0) mustwait = true; 2211 2212#ifdef CONFIG_FB_SIS_315 2213 if(ivideo->sisvga_engine == SIS_315_VGA) { 2214 inSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,cr63); 2215 cr63 &= 0x40; 2216 andSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,0xBF); 2217 } 2218#endif 2219 2220 inSISIDXREG(SISCR,0x17,cr17); 2221 cr17 &= 0x80; 2222 if(!cr17) { 2223 orSISIDXREG(SISCR,0x17,0x80); 2224 mustwait = true; 2225 outSISIDXREG(SISSR, 0x00, 0x01); 2226 outSISIDXREG(SISSR, 0x00, 0x03); 2227 } 2228 2229 if(mustwait) { 2230 for(i=0; i < 10; i++) sisfbwaitretracecrt1(ivideo); 2231 } 2232 2233#ifdef CONFIG_FB_SIS_315 2234 if(ivideo->chip >= SIS_330) { 2235 andSISIDXREG(SISCR,0x32,~0x20); 2236 if(ivideo->chip >= SIS_340) { 2237 outSISIDXREG(SISCR, 0x57, 0x4a); 2238 } else { 2239 outSISIDXREG(SISCR, 0x57, 0x5f); 2240 } 2241 orSISIDXREG(SISCR, 0x53, 0x02); 2242 while((inSISREG(SISINPSTAT)) & 0x01) break; 2243 while(!((inSISREG(SISINPSTAT)) & 0x01)) break; 2244 if((inSISREG(SISMISCW)) & 0x10) temp = 1; 2245 andSISIDXREG(SISCR, 0x53, 0xfd); 2246 andSISIDXREG(SISCR, 0x57, 0x00); 2247 } 2248#endif 2249 2250 if(temp == 0xffff) { 2251 i = 3; 2252 do { 2253 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, 2254 ivideo->sisvga_engine, 0, 0, NULL, ivideo->vbflags2); 2255 } while(((temp == 0) || (temp == 0xffff)) && i--); 2256 2257 if((temp == 0) || (temp == 0xffff)) { 2258 if(sisfb_test_DDC1(ivideo)) temp = 1; 2259 } 2260 } 2261 2262 if((temp) && (temp != 0xffff)) { 2263 orSISIDXREG(SISCR,0x32,0x20); 2264 } 2265 2266#ifdef CONFIG_FB_SIS_315 2267 if(ivideo->sisvga_engine == SIS_315_VGA) { 2268 setSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,0xBF,cr63); 2269 } 2270#endif 2271 2272 setSISIDXREG(SISCR,0x17,0x7F,cr17); 2273 2274 outSISIDXREG(SISSR,0x1F,sr1F); 2275} 2276 2277/* Determine and detect attached devices on SiS30x */ 2278static void __devinit 2279SiS_SenseLCD(struct sis_video_info *ivideo) 2280{ 2281 unsigned char buffer[256]; 2282 unsigned short temp, realcrtno, i; 2283 u8 reg, cr37 = 0, paneltype = 0; 2284 u16 xres, yres; 2285 2286 ivideo->SiS_Pr.PanelSelfDetected = false; 2287 2288 /* LCD detection only for TMDS bridges */ 2289 if(!(ivideo->vbflags2 & VB2_SISTMDSBRIDGE)) 2290 return; 2291 if(ivideo->vbflags2 & VB2_30xBDH) 2292 return; 2293 2294 /* If LCD already set up by BIOS, skip it */ 2295 inSISIDXREG(SISCR, 0x32, reg); 2296 if(reg & 0x08) 2297 return; 2298 2299 realcrtno = 1; 2300 if(ivideo->SiS_Pr.DDCPortMixup) 2301 realcrtno = 0; 2302 2303 /* Check DDC capabilities */ 2304 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine, 2305 realcrtno, 0, &buffer[0], ivideo->vbflags2); 2306 2307 if((!temp) || (temp == 0xffff) || (!(temp & 0x02))) 2308 return; 2309 2310 /* Read DDC data */ 2311 i = 3; /* Number of retrys */ 2312 do { 2313 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, 2314 ivideo->sisvga_engine, realcrtno, 1, 2315 &buffer[0], ivideo->vbflags2); 2316 } while((temp) && i--); 2317 2318 if(temp) 2319 return; 2320 2321 /* No digital device */ 2322 if(!(buffer[0x14] & 0x80)) 2323 return; 2324 2325 /* First detailed timing preferred timing? */ 2326 if(!(buffer[0x18] & 0x02)) 2327 return; 2328 2329 xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4); 2330 yres = buffer[0x3b] | ((buffer[0x3d] & 0xf0) << 4); 2331 2332 switch(xres) { 2333 case 1024: 2334 if(yres == 768) 2335 paneltype = 0x02; 2336 break; 2337 case 1280: 2338 if(yres == 1024) 2339 paneltype = 0x03; 2340 break; 2341 case 1600: 2342 if((yres == 1200) && (ivideo->vbflags2 & VB2_30xC)) 2343 paneltype = 0x0b; 2344 break; 2345 } 2346 2347 if(!paneltype) 2348 return; 2349 2350 if(buffer[0x23]) 2351 cr37 |= 0x10; 2352 2353 if((buffer[0x47] & 0x18) == 0x18) 2354 cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20); 2355 else 2356 cr37 |= 0xc0; 2357 2358 outSISIDXREG(SISCR, 0x36, paneltype); 2359 cr37 &= 0xf1; 2360 setSISIDXREG(SISCR, 0x37, 0x0c, cr37); 2361 orSISIDXREG(SISCR, 0x32, 0x08); 2362 2363 ivideo->SiS_Pr.PanelSelfDetected = true; 2364} 2365 2366static int __devinit 2367SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test) 2368{ 2369 int temp, mytest, result, i, j; 2370 2371 for(j = 0; j < 10; j++) { 2372 result = 0; 2373 for(i = 0; i < 3; i++) { 2374 mytest = test; 2375 outSISIDXREG(SISPART4,0x11,(type & 0x00ff)); 2376 temp = (type >> 8) | (mytest & 0x00ff); 2377 setSISIDXREG(SISPART4,0x10,0xe0,temp); 2378 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1500); 2379 mytest >>= 8; 2380 mytest &= 0x7f; 2381 inSISIDXREG(SISPART4,0x03,temp); 2382 temp ^= 0x0e; 2383 temp &= mytest; 2384 if(temp == mytest) result++; 2385 outSISIDXREG(SISPART4,0x11,0x00); 2386 andSISIDXREG(SISPART4,0x10,0xe0); 2387 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1000); 2388 } 2389 if((result == 0) || (result >= 2)) break; 2390 } 2391 return result; 2392} 2393 2394static void __devinit 2395SiS_Sense30x(struct sis_video_info *ivideo) 2396{ 2397 u8 backupP4_0d,backupP2_00,backupP2_4d,backupSR_1e,biosflag=0; 2398 u16 svhs=0, svhs_c=0; 2399 u16 cvbs=0, cvbs_c=0; 2400 u16 vga2=0, vga2_c=0; 2401 int myflag, result; 2402 char stdstr[] = "sisfb: Detected"; 2403 char tvstr[] = "TV connected to"; 2404 2405 if(ivideo->vbflags2 & VB2_301) { 2406 svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1; 2407 inSISIDXREG(SISPART4,0x01,myflag); 2408 if(myflag & 0x04) { 2409 svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd; 2410 } 2411 } else if(ivideo->vbflags2 & (VB2_301B | VB2_302B)) { 2412 svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190; 2413 } else if(ivideo->vbflags2 & (VB2_301LV | VB2_302LV)) { 2414 svhs = 0x0200; cvbs = 0x0100; 2415 } else if(ivideo->vbflags2 & (VB2_301C | VB2_302ELV | VB2_307T | VB2_307LV)) { 2416 svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190; 2417 } else 2418 return; 2419 2420 vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804; 2421 if(ivideo->vbflags & (VB2_301LV|VB2_302LV|VB2_302ELV|VB2_307LV)) { 2422 svhs_c = 0x0408; cvbs_c = 0x0808; 2423 } 2424 2425 biosflag = 2; 2426 if(ivideo->haveXGIROM) { 2427 biosflag = ivideo->bios_abase[0x58] & 0x03; 2428 } else if(ivideo->newrom) { 2429 if(ivideo->bios_abase[0x5d] & 0x04) biosflag |= 0x01; 2430 } else if(ivideo->sisvga_engine == SIS_300_VGA) { 2431 if(ivideo->bios_abase) { 2432 biosflag = ivideo->bios_abase[0xfe] & 0x03; 2433 } 2434 } 2435 2436 if(ivideo->chip == SIS_300) { 2437 inSISIDXREG(SISSR,0x3b,myflag); 2438 if(!(myflag & 0x01)) vga2 = vga2_c = 0; 2439 } 2440 2441 if(!(ivideo->vbflags2 & VB2_SISVGA2BRIDGE)) { 2442 vga2 = vga2_c = 0; 2443 } 2444 2445 inSISIDXREG(SISSR,0x1e,backupSR_1e); 2446 orSISIDXREG(SISSR,0x1e,0x20); 2447 2448 inSISIDXREG(SISPART4,0x0d,backupP4_0d); 2449 if(ivideo->vbflags2 & VB2_30xC) { 2450 setSISIDXREG(SISPART4,0x0d,~0x07,0x01); 2451 } else { 2452 orSISIDXREG(SISPART4,0x0d,0x04); 2453 } 2454 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000); 2455 2456 inSISIDXREG(SISPART2,0x00,backupP2_00); 2457 outSISIDXREG(SISPART2,0x00,((backupP2_00 | 0x1c) & 0xfc)); 2458 2459 inSISIDXREG(SISPART2,0x4d,backupP2_4d); 2460 if(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE) { 2461 outSISIDXREG(SISPART2,0x4d,(backupP2_4d & ~0x10)); 2462 } 2463 2464 if(!(ivideo->vbflags2 & VB2_30xCLV)) { 2465 SISDoSense(ivideo, 0, 0); 2466 } 2467 2468 andSISIDXREG(SISCR, 0x32, ~0x14); 2469 2470 if(vga2_c || vga2) { 2471 if(SISDoSense(ivideo, vga2, vga2_c)) { 2472 if(biosflag & 0x01) { 2473 printk(KERN_INFO "%s %s SCART output\n", stdstr, tvstr); 2474 orSISIDXREG(SISCR, 0x32, 0x04); 2475 } else { 2476 printk(KERN_INFO "%s secondary VGA connection\n", stdstr); 2477 orSISIDXREG(SISCR, 0x32, 0x10); 2478 } 2479 } 2480 } 2481 2482 andSISIDXREG(SISCR, 0x32, 0x3f); 2483 2484 if(ivideo->vbflags2 & VB2_30xCLV) { 2485 orSISIDXREG(SISPART4,0x0d,0x04); 2486 } 2487 2488 if((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) { 2489 outSISIDXREG(SISPART2,0x4d,(backupP2_4d | 0x10)); 2490 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000); 2491 if((result = SISDoSense(ivideo, svhs, 0x0604))) { 2492 if((result = SISDoSense(ivideo, cvbs, 0x0804))) { 2493 printk(KERN_INFO "%s %s YPbPr component output\n", stdstr, tvstr); 2494 orSISIDXREG(SISCR,0x32,0x80); 2495 } 2496 } 2497 outSISIDXREG(SISPART2,0x4d,backupP2_4d); 2498 } 2499 2500 andSISIDXREG(SISCR, 0x32, ~0x03); 2501 2502 if(!(ivideo->vbflags & TV_YPBPR)) { 2503 if((result = SISDoSense(ivideo, svhs, svhs_c))) { 2504 printk(KERN_INFO "%s %s SVIDEO output\n", stdstr, tvstr); 2505 orSISIDXREG(SISCR, 0x32, 0x02); 2506 } 2507 if((biosflag & 0x02) || (!result)) { 2508 if(SISDoSense(ivideo, cvbs, cvbs_c)) { 2509 printk(KERN_INFO "%s %s COMPOSITE output\n", stdstr, tvstr); 2510 orSISIDXREG(SISCR, 0x32, 0x01); 2511 } 2512 } 2513 } 2514 2515 SISDoSense(ivideo, 0, 0); 2516 2517 outSISIDXREG(SISPART2,0x00,backupP2_00); 2518 outSISIDXREG(SISPART4,0x0d,backupP4_0d); 2519 outSISIDXREG(SISSR,0x1e,backupSR_1e); 2520 2521 if(ivideo->vbflags2 & VB2_30xCLV) { 2522 inSISIDXREG(SISPART2,0x00,biosflag); 2523 if(biosflag & 0x20) { 2524 for(myflag = 2; myflag > 0; myflag--) { 2525 biosflag ^= 0x20; 2526 outSISIDXREG(SISPART2,0x00,biosflag); 2527 } 2528 } 2529 } 2530 2531 outSISIDXREG(SISPART2,0x00,backupP2_00); 2532} 2533 2534/* Determine and detect attached TV's on Chrontel */ 2535static void __devinit 2536SiS_SenseCh(struct sis_video_info *ivideo) 2537{ 2538#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315) 2539 u8 temp1, temp2; 2540 char stdstr[] = "sisfb: Chrontel: Detected TV connected to"; 2541#endif 2542#ifdef CONFIG_FB_SIS_300 2543 unsigned char test[3]; 2544 int i; 2545#endif 2546 2547 if(ivideo->chip < SIS_315H) { 2548 2549#ifdef CONFIG_FB_SIS_300 2550 ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 1; /* Chrontel 700x */ 2551 SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x9c); /* Set general purpose IO for Chrontel communication */ 2552 SiS_DDC2Delay(&ivideo->SiS_Pr, 1000); 2553 temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25); 2554 /* See Chrontel TB31 for explanation */ 2555 temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e); 2556 if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) { 2557 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e, 0x0b); 2558 SiS_DDC2Delay(&ivideo->SiS_Pr, 300); 2559 } 2560 temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25); 2561 if(temp2 != temp1) temp1 = temp2; 2562 2563 if((temp1 >= 0x22) && (temp1 <= 0x50)) { 2564 /* Read power status */ 2565 temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e); 2566 if((temp1 & 0x03) != 0x03) { 2567 /* Power all outputs */ 2568 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e,0x0b); 2569 SiS_DDC2Delay(&ivideo->SiS_Pr, 300); 2570 } 2571 /* Sense connected TV devices */ 2572 for(i = 0; i < 3; i++) { 2573 SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x01); 2574 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96); 2575 SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x00); 2576 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96); 2577 temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x10); 2578 if(!(temp1 & 0x08)) test[i] = 0x02; 2579 else if(!(temp1 & 0x02)) test[i] = 0x01; 2580 else test[i] = 0; 2581 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96); 2582 } 2583 2584 if(test[0] == test[1]) temp1 = test[0]; 2585 else if(test[0] == test[2]) temp1 = test[0]; 2586 else if(test[1] == test[2]) temp1 = test[1]; 2587 else { 2588 printk(KERN_INFO 2589 "sisfb: TV detection unreliable - test results varied\n"); 2590 temp1 = test[2]; 2591 } 2592 if(temp1 == 0x02) { 2593 printk(KERN_INFO "%s SVIDEO output\n", stdstr); 2594 ivideo->vbflags |= TV_SVIDEO; 2595 orSISIDXREG(SISCR, 0x32, 0x02); 2596 andSISIDXREG(SISCR, 0x32, ~0x05); 2597 } else if (temp1 == 0x01) { 2598 printk(KERN_INFO "%s CVBS output\n", stdstr); 2599 ivideo->vbflags |= TV_AVIDEO; 2600 orSISIDXREG(SISCR, 0x32, 0x01); 2601 andSISIDXREG(SISCR, 0x32, ~0x06); 2602 } else { 2603 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8); 2604 andSISIDXREG(SISCR, 0x32, ~0x07); 2605 } 2606 } else if(temp1 == 0) { 2607 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8); 2608 andSISIDXREG(SISCR, 0x32, ~0x07); 2609 } 2610 /* Set general purpose IO for Chrontel communication */ 2611 SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x00); 2612#endif 2613 2614 } else { 2615 2616#ifdef CONFIG_FB_SIS_315 2617 ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 2; /* Chrontel 7019 */ 2618 temp1 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x49); 2619 SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, 0x20); 2620 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96); 2621 temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20); 2622 temp2 |= 0x01; 2623 SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2); 2624 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96); 2625 temp2 ^= 0x01; 2626 SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2); 2627 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96); 2628 temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20); 2629 SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, temp1); 2630 temp1 = 0; 2631 if(temp2 & 0x02) temp1 |= 0x01; 2632 if(temp2 & 0x10) temp1 |= 0x01; 2633 if(temp2 & 0x04) temp1 |= 0x02; 2634 if( (temp1 & 0x01) && (temp1 & 0x02) ) temp1 = 0x04; 2635 switch(temp1) { 2636 case 0x01: 2637 printk(KERN_INFO "%s CVBS output\n", stdstr); 2638 ivideo->vbflags |= TV_AVIDEO; 2639 orSISIDXREG(SISCR, 0x32, 0x01); 2640 andSISIDXREG(SISCR, 0x32, ~0x06); 2641 break; 2642 case 0x02: 2643 printk(KERN_INFO "%s SVIDEO output\n", stdstr); 2644 ivideo->vbflags |= TV_SVIDEO; 2645 orSISIDXREG(SISCR, 0x32, 0x02); 2646 andSISIDXREG(SISCR, 0x32, ~0x05); 2647 break; 2648 case 0x04: 2649 printk(KERN_INFO "%s SCART output\n", stdstr); 2650 orSISIDXREG(SISCR, 0x32, 0x04); 2651 andSISIDXREG(SISCR, 0x32, ~0x03); 2652 break; 2653 default: 2654 andSISIDXREG(SISCR, 0x32, ~0x07); 2655 } 2656#endif 2657 } 2658} 2659 2660static void __devinit 2661sisfb_get_VB_type(struct sis_video_info *ivideo) 2662{ 2663 char stdstr[] = "sisfb: Detected"; 2664 char bridgestr[] = "video bridge"; 2665 u8 vb_chipid; 2666 u8 reg; 2667 2668 /* No CRT2 on XGI Z7 */ 2669 if(ivideo->chip == XGI_20) 2670 return; 2671 2672 inSISIDXREG(SISPART4, 0x00, vb_chipid); 2673 switch(vb_chipid) { 2674 case 0x01: 2675 inSISIDXREG(SISPART4, 0x01, reg); 2676 if(reg < 0xb0) { 2677 ivideo->vbflags |= VB_301; /* Deprecated */ 2678 ivideo->vbflags2 |= VB2_301; 2679 printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr); 2680 } else if(reg < 0xc0) { 2681 ivideo->vbflags |= VB_301B; /* Deprecated */ 2682 ivideo->vbflags2 |= VB2_301B; 2683 inSISIDXREG(SISPART4,0x23,reg); 2684 if(!(reg & 0x02)) { 2685 ivideo->vbflags |= VB_30xBDH; /* Deprecated */ 2686 ivideo->vbflags2 |= VB2_30xBDH; 2687 printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr); 2688 } else { 2689 printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr); 2690 } 2691 } else if(reg < 0xd0) { 2692 ivideo->vbflags |= VB_301C; /* Deprecated */ 2693 ivideo->vbflags2 |= VB2_301C; 2694 printk(KERN_INFO "%s SiS301C %s\n", stdstr, bridgestr); 2695 } else if(reg < 0xe0) { 2696 ivideo->vbflags |= VB_301LV; /* Deprecated */ 2697 ivideo->vbflags2 |= VB2_301LV; 2698 printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr); 2699 } else if(reg <= 0xe1) { 2700 inSISIDXREG(SISPART4,0x39,reg); 2701 if(reg == 0xff) { 2702 ivideo->vbflags |= VB_302LV; /* Deprecated */ 2703 ivideo->vbflags2 |= VB2_302LV; 2704 printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr); 2705 } else { 2706 ivideo->vbflags |= VB_301C; /* Deprecated */ 2707 ivideo->vbflags2 |= VB2_301C; 2708 printk(KERN_INFO "%s SiS301C(P4) %s\n", stdstr, bridgestr); 2709 } 2710 } 2711 break; 2712 case 0x02: 2713 ivideo->vbflags |= VB_302B; /* Deprecated */ 2714 ivideo->vbflags2 |= VB2_302B; 2715 printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr); 2716 break; 2717 } 2718 2719 if((!(ivideo->vbflags2 & VB2_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) { 2720 inSISIDXREG(SISCR, 0x37, reg); 2721 reg &= SIS_EXTERNAL_CHIP_MASK; 2722 reg >>= 1; 2723 if(ivideo->sisvga_engine == SIS_300_VGA) { 2724#ifdef CONFIG_FB_SIS_300 2725 switch(reg) { 2726 case SIS_EXTERNAL_CHIP_LVDS: 2727 ivideo->vbflags |= VB_LVDS; /* Deprecated */ 2728 ivideo->vbflags2 |= VB2_LVDS; 2729 break; 2730 case SIS_EXTERNAL_CHIP_TRUMPION: 2731 ivideo->vbflags |= (VB_LVDS | VB_TRUMPION); /* Deprecated */ 2732 ivideo->vbflags2 |= (VB2_LVDS | VB2_TRUMPION); 2733 break; 2734 case SIS_EXTERNAL_CHIP_CHRONTEL: 2735 ivideo->vbflags |= VB_CHRONTEL; /* Deprecated */ 2736 ivideo->vbflags2 |= VB2_CHRONTEL; 2737 break; 2738 case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL: 2739 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */ 2740 ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL); 2741 break; 2742 } 2743 if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 1; 2744#endif 2745 } else if(ivideo->chip < SIS_661) { 2746#ifdef CONFIG_FB_SIS_315 2747 switch (reg) { 2748 case SIS310_EXTERNAL_CHIP_LVDS: 2749 ivideo->vbflags |= VB_LVDS; /* Deprecated */ 2750 ivideo->vbflags2 |= VB2_LVDS; 2751 break; 2752 case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL: 2753 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */ 2754 ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL); 2755 break; 2756 } 2757 if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2; 2758#endif 2759 } else if(ivideo->chip >= SIS_661) { 2760#ifdef CONFIG_FB_SIS_315 2761 inSISIDXREG(SISCR, 0x38, reg); 2762 reg >>= 5; 2763 switch(reg) { 2764 case 0x02: 2765 ivideo->vbflags |= VB_LVDS; /* Deprecated */ 2766 ivideo->vbflags2 |= VB2_LVDS; 2767 break; 2768 case 0x03: 2769 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */ 2770 ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL); 2771 break; 2772 case 0x04: 2773 ivideo->vbflags |= (VB_LVDS | VB_CONEXANT); /* Deprecated */ 2774 ivideo->vbflags2 |= (VB2_LVDS | VB2_CONEXANT); 2775 break; 2776 } 2777 if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2; 2778#endif 2779 } 2780 if(ivideo->vbflags2 & VB2_LVDS) { 2781 printk(KERN_INFO "%s LVDS transmitter\n", stdstr); 2782 } 2783 if((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags2 & VB2_TRUMPION)) { 2784 printk(KERN_INFO "%s Trumpion Zurac LCD scaler\n", stdstr); 2785 } 2786 if(ivideo->vbflags2 & VB2_CHRONTEL) { 2787 printk(KERN_INFO "%s Chrontel TV encoder\n", stdstr); 2788 } 2789 if((ivideo->chip >= SIS_661) && (ivideo->vbflags2 & VB2_CONEXANT)) { 2790 printk(KERN_INFO "%s Conexant external device\n", stdstr); 2791 } 2792 } 2793 2794 if(ivideo->vbflags2 & VB2_SISBRIDGE) { 2795 SiS_SenseLCD(ivideo); 2796 SiS_Sense30x(ivideo); 2797 } else if(ivideo->vbflags2 & VB2_CHRONTEL) { 2798 SiS_SenseCh(ivideo); 2799 } 2800} 2801 2802/* ---------- Engine initialization routines ------------ */ 2803 2804static void 2805sisfb_engine_init(struct sis_video_info *ivideo) 2806{ 2807 2808 /* Initialize command queue (we use MMIO only) */ 2809 2810 /* BEFORE THIS IS CALLED, THE ENGINES *MUST* BE SYNC'ED */ 2811 2812 ivideo->caps &= ~(TURBO_QUEUE_CAP | 2813 MMIO_CMD_QUEUE_CAP | 2814 VM_CMD_QUEUE_CAP | 2815 AGP_CMD_QUEUE_CAP); 2816 2817#ifdef CONFIG_FB_SIS_300 2818 if(ivideo->sisvga_engine == SIS_300_VGA) { 2819 u32 tqueue_pos; 2820 u8 tq_state; 2821 2822 tqueue_pos = (ivideo->video_size - ivideo->cmdQueueSize) / (64 * 1024); 2823 2824 inSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state); 2825 tq_state |= 0xf0; 2826 tq_state &= 0xfc; 2827 tq_state |= (u8)(tqueue_pos >> 8); 2828 outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state); 2829 2830 outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff)); 2831 2832 ivideo->caps |= TURBO_QUEUE_CAP; 2833 } 2834#endif 2835 2836#ifdef CONFIG_FB_SIS_315 2837 if(ivideo->sisvga_engine == SIS_315_VGA) { 2838 u32 tempq = 0, templ; 2839 u8 temp; 2840 2841 if(ivideo->chip == XGI_20) { 2842 switch(ivideo->cmdQueueSize) { 2843 case (64 * 1024): 2844 temp = SIS_CMD_QUEUE_SIZE_Z7_64k; 2845 break; 2846 case (128 * 1024): 2847 default: 2848 temp = SIS_CMD_QUEUE_SIZE_Z7_128k; 2849 } 2850 } else { 2851 switch(ivideo->cmdQueueSize) { 2852 case (4 * 1024 * 1024): 2853 temp = SIS_CMD_QUEUE_SIZE_4M; 2854 break; 2855 case (2 * 1024 * 1024): 2856 temp = SIS_CMD_QUEUE_SIZE_2M; 2857 break; 2858 case (1 * 1024 * 1024): 2859 temp = SIS_CMD_QUEUE_SIZE_1M; 2860 break; 2861 default: 2862 case (512 * 1024): 2863 temp = SIS_CMD_QUEUE_SIZE_512k; 2864 } 2865 } 2866 2867 outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD); 2868 outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET); 2869 2870 if((ivideo->chip >= XGI_40) && ivideo->modechanged) { 2871 /* Must disable dual pipe on XGI_40. Can't do 2872 * this in MMIO mode, because it requires 2873 * setting/clearing a bit in the MMIO fire trigger 2874 * register. 2875 */ 2876 if(!((templ = MMIO_IN32(ivideo->mmio_vbase, 0x8240)) & (1 << 10))) { 2877 2878 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, 0); 2879 2880 outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, (temp | SIS_VRAM_CMDQUEUE_ENABLE)); 2881 2882 tempq = MMIO_IN32(ivideo->mmio_vbase, Q_READ_PTR); 2883 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, tempq); 2884 2885 tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize); 2886 MMIO_OUT32(ivideo->mmio_vbase, Q_BASE_ADDR, tempq); 2887 2888 writel(0x16800000 + 0x8240, ivideo->video_vbase + tempq); 2889 writel(templ | (1 << 10), ivideo->video_vbase + tempq + 4); 2890 writel(0x168F0000, ivideo->video_vbase + tempq + 8); 2891 writel(0x168F0000, ivideo->video_vbase + tempq + 12); 2892 2893 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, (tempq + 16)); 2894 2895 sisfb_syncaccel(ivideo); 2896 2897 outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET); 2898 2899 } 2900 } 2901 2902 tempq = MMIO_IN32(ivideo->mmio_vbase, MMIO_QUEUE_READPORT); 2903 MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq); 2904 2905 temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR); 2906 outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp); 2907 2908 tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize); 2909 MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq); 2910 2911 ivideo->caps |= MMIO_CMD_QUEUE_CAP; 2912 } 2913#endif 2914 2915 ivideo->engineok = 1; 2916} 2917 2918static void __devinit 2919sisfb_detect_lcd_type(struct sis_video_info *ivideo) 2920{ 2921 u8 reg; 2922 int i; 2923 2924 inSISIDXREG(SISCR, 0x36, reg); 2925 reg &= 0x0f; 2926 if(ivideo->sisvga_engine == SIS_300_VGA) { 2927 ivideo->CRT2LCDType = sis300paneltype[reg]; 2928 } else if(ivideo->chip >= SIS_661) { 2929 ivideo->CRT2LCDType = sis661paneltype[reg]; 2930 } else { 2931 ivideo->CRT2LCDType = sis310paneltype[reg]; 2932 if((ivideo->chip == SIS_550) && (sisfb_fstn)) { 2933 if((ivideo->CRT2LCDType != LCD_320x240_2) && 2934 (ivideo->CRT2LCDType != LCD_320x240_3)) { 2935 ivideo->CRT2LCDType = LCD_320x240; 2936 } 2937 } 2938 } 2939 2940 if(ivideo->CRT2LCDType == LCD_UNKNOWN) { 2941 /* For broken BIOSes: Assume 1024x768, RGB18 */ 2942 ivideo->CRT2LCDType = LCD_1024x768; 2943 setSISIDXREG(SISCR,0x36,0xf0,0x02); 2944 setSISIDXREG(SISCR,0x37,0xee,0x01); 2945 printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg); 2946 } 2947 2948 for(i = 0; i < SIS_LCD_NUMBER; i++) { 2949 if(ivideo->CRT2LCDType == sis_lcd_data[i].lcdtype) { 2950 ivideo->lcdxres = sis_lcd_data[i].xres; 2951 ivideo->lcdyres = sis_lcd_data[i].yres; 2952 ivideo->lcddefmodeidx = sis_lcd_data[i].default_mode_idx; 2953 break; 2954 } 2955 } 2956 2957#ifdef CONFIG_FB_SIS_300 2958 if(ivideo->SiS_Pr.SiS_CustomT == CUT_BARCO1366) { 2959 ivideo->lcdxres = 1360; ivideo->lcdyres = 1024; 2960 ivideo->lcddefmodeidx = DEFAULT_MODE_1360; 2961 } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL848) { 2962 ivideo->lcdxres = 848; ivideo->lcdyres = 480; 2963 ivideo->lcddefmodeidx = DEFAULT_MODE_848; 2964 } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL856) { 2965 ivideo->lcdxres = 856; ivideo->lcdyres = 480; 2966 ivideo->lcddefmodeidx = DEFAULT_MODE_856; 2967 } 2968#endif 2969 2970 printk(KERN_DEBUG "sisfb: Detected %dx%d flat panel\n", 2971 ivideo->lcdxres, ivideo->lcdyres); 2972} 2973 2974static void __devinit 2975sisfb_save_pdc_emi(struct sis_video_info *ivideo) 2976{ 2977#ifdef CONFIG_FB_SIS_300 2978 /* Save the current PanelDelayCompensation if the LCD is currently used */ 2979 if(ivideo->sisvga_engine == SIS_300_VGA) { 2980 if(ivideo->vbflags2 & (VB2_LVDS | VB2_30xBDH)) { 2981 int tmp; 2982 inSISIDXREG(SISCR,0x30,tmp); 2983 if(tmp & 0x20) { 2984 /* Currently on LCD? If yes, read current pdc */ 2985 inSISIDXREG(SISPART1,0x13,ivideo->detectedpdc); 2986 ivideo->detectedpdc &= 0x3c; 2987 if(ivideo->SiS_Pr.PDC == -1) { 2988 /* Let option override detection */ 2989 ivideo->SiS_Pr.PDC = ivideo->detectedpdc; 2990 } 2991 printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n", 2992 ivideo->detectedpdc); 2993 } 2994 if((ivideo->SiS_Pr.PDC != -1) && 2995 (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) { 2996 printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n", 2997 ivideo->SiS_Pr.PDC); 2998 } 2999 } 3000 } 3001#endif 3002 3003#ifdef CONFIG_FB_SIS_315 3004 if(ivideo->sisvga_engine == SIS_315_VGA) { 3005 3006 /* Try to find about LCDA */ 3007 if(ivideo->vbflags2 & VB2_SISLCDABRIDGE) { 3008 int tmp; 3009 inSISIDXREG(SISPART1,0x13,tmp); 3010 if(tmp & 0x04) { 3011 ivideo->SiS_Pr.SiS_UseLCDA = true; 3012 ivideo->detectedlcda = 0x03; 3013 } 3014 } 3015 3016 /* Save PDC */ 3017 if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) { 3018 int tmp; 3019 inSISIDXREG(SISCR,0x30,tmp); 3020 if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) { 3021 /* Currently on LCD? If yes, read current pdc */ 3022 u8 pdc; 3023 inSISIDXREG(SISPART1,0x2D,pdc); 3024 ivideo->detectedpdc = (pdc & 0x0f) << 1; 3025 ivideo->detectedpdca = (pdc & 0xf0) >> 3; 3026 inSISIDXREG(SISPART1,0x35,pdc); 3027 ivideo->detectedpdc |= ((pdc >> 7) & 0x01); 3028 inSISIDXREG(SISPART1,0x20,pdc); 3029 ivideo->detectedpdca |= ((pdc >> 6) & 0x01); 3030 if(ivideo->newrom) { 3031 /* New ROM invalidates other PDC resp. */ 3032 if(ivideo->detectedlcda != 0xff) { 3033 ivideo->detectedpdc = 0xff; 3034 } else { 3035 ivideo->detectedpdca = 0xff; 3036 } 3037 } 3038 if(ivideo->SiS_Pr.PDC == -1) { 3039 if(ivideo->detectedpdc != 0xff) { 3040 ivideo->SiS_Pr.PDC = ivideo->detectedpdc; 3041 } 3042 } 3043 if(ivideo->SiS_Pr.PDCA == -1) { 3044 if(ivideo->detectedpdca != 0xff) { 3045 ivideo->SiS_Pr.PDCA = ivideo->detectedpdca; 3046 } 3047 } 3048 if(ivideo->detectedpdc != 0xff) { 3049 printk(KERN_INFO 3050 "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n", 3051 ivideo->detectedpdc); 3052 } 3053 if(ivideo->detectedpdca != 0xff) { 3054 printk(KERN_INFO 3055 "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n", 3056 ivideo->detectedpdca); 3057 } 3058 } 3059 3060 /* Save EMI */ 3061 if(ivideo->vbflags2 & VB2_SISEMIBRIDGE) { 3062 inSISIDXREG(SISPART4,0x30,ivideo->SiS_Pr.EMI_30); 3063 inSISIDXREG(SISPART4,0x31,ivideo->SiS_Pr.EMI_31); 3064 inSISIDXREG(SISPART4,0x32,ivideo->SiS_Pr.EMI_32); 3065 inSISIDXREG(SISPART4,0x33,ivideo->SiS_Pr.EMI_33); 3066 ivideo->SiS_Pr.HaveEMI = true; 3067 if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) { 3068 ivideo->SiS_Pr.HaveEMILCD = true; 3069 } 3070 } 3071 } 3072 3073 /* Let user override detected PDCs (all bridges) */ 3074 if(ivideo->vbflags2 & VB2_30xBLV) { 3075 if((ivideo->SiS_Pr.PDC != -1) && 3076 (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) { 3077 printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n", 3078 ivideo->SiS_Pr.PDC); 3079 } 3080 if((ivideo->SiS_Pr.PDCA != -1) && 3081 (ivideo->SiS_Pr.PDCA != ivideo->detectedpdca)) { 3082 printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n", 3083 ivideo->SiS_Pr.PDCA); 3084 } 3085 } 3086 3087 } 3088#endif 3089} 3090 3091/* -------------------- Memory manager routines ---------------------- */ 3092 3093static u32 __devinit 3094sisfb_getheapstart(struct sis_video_info *ivideo) 3095{ 3096 u32 ret = ivideo->sisfb_parm_mem * 1024; 3097 u32 maxoffs = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize; 3098 u32 def; 3099 3100 /* Calculate heap start = end of memory for console 3101 * 3102 * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ 3103 * C = console, D = heap, H = HWCursor, Q = cmd-queue 3104 * 3105 * On 76x in UMA+LFB mode, the layout is as follows: 3106 * DDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCHHHHQQQQQQQQQQQ 3107 * where the heap is the entire UMA area, eventually 3108 * into the LFB area if the given mem parameter is 3109 * higher than the size of the UMA memory. 3110 * 3111 * Basically given by "mem" parameter 3112 * 3113 * maximum = videosize - cmd_queue - hwcursor 3114 * (results in a heap of size 0) 3115 * default = SiS 300: depends on videosize 3116 * SiS 315/330/340/XGI: 32k below max 3117 */ 3118 3119 if(ivideo->sisvga_engine == SIS_300_VGA) { 3120 if(ivideo->video_size > 0x1000000) { 3121 def = 0xc00000; 3122 } else if(ivideo->video_size > 0x800000) { 3123 def = 0x800000; 3124 } else { 3125 def = 0x400000; 3126 } 3127 } else if(ivideo->UMAsize && ivideo->LFBsize) { 3128 ret = def = 0; 3129 } else { 3130 def = maxoffs - 0x8000; 3131 } 3132 3133 if((!ret) || (ret > maxoffs) || (ivideo->cardnumber != 0)) 3134 ret = def; 3135 3136 return ret; 3137} 3138 3139static u32 __devinit 3140sisfb_getheapsize(struct sis_video_info *ivideo) 3141{ 3142 u32 max = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize; 3143 u32 ret = 0; 3144 3145 if(ivideo->UMAsize && ivideo->LFBsize) { 3146 if( (!ivideo->sisfb_parm_mem) || 3147 ((ivideo->sisfb_parm_mem * 1024) > max) || 3148 ((max - (ivideo->sisfb_parm_mem * 1024)) < ivideo->UMAsize) ) { 3149 ret = ivideo->UMAsize; 3150 max -= ivideo->UMAsize; 3151 } else { 3152 ret = max - (ivideo->sisfb_parm_mem * 1024); 3153 max = ivideo->sisfb_parm_mem * 1024; 3154 } 3155 ivideo->video_offset = ret; 3156 ivideo->sisfb_mem = max; 3157 } else { 3158 ret = max - ivideo->heapstart; 3159 ivideo->sisfb_mem = ivideo->heapstart; 3160 } 3161 3162 return ret; 3163} 3164 3165static int __devinit 3166sisfb_heap_init(struct sis_video_info *ivideo) 3167{ 3168 struct SIS_OH *poh; 3169 3170 ivideo->video_offset = 0; 3171 if(ivideo->sisfb_parm_mem) { 3172 if( (ivideo->sisfb_parm_mem < (2 * 1024 * 1024)) || 3173 (ivideo->sisfb_parm_mem > ivideo->video_size) ) { 3174 ivideo->sisfb_parm_mem = 0; 3175 } 3176 } 3177 3178 ivideo->heapstart = sisfb_getheapstart(ivideo); 3179 ivideo->sisfb_heap_size = sisfb_getheapsize(ivideo); 3180 3181 ivideo->sisfb_heap_start = ivideo->video_vbase + ivideo->heapstart; 3182 ivideo->sisfb_heap_end = ivideo->sisfb_heap_start + ivideo->sisfb_heap_size; 3183 3184 printk(KERN_INFO "sisfb: Memory heap starting at %dK, size %dK\n", 3185 (int)(ivideo->heapstart / 1024), (int)(ivideo->sisfb_heap_size / 1024)); 3186 3187 ivideo->sisfb_heap.vinfo = ivideo; 3188 3189 ivideo->sisfb_heap.poha_chain = NULL; 3190 ivideo->sisfb_heap.poh_freelist = NULL; 3191 3192 poh = sisfb_poh_new_node(&ivideo->sisfb_heap); 3193 if(poh == NULL) 3194 return 1; 3195 3196 poh->poh_next = &ivideo->sisfb_heap.oh_free; 3197 poh->poh_prev = &ivideo->sisfb_heap.oh_free; 3198 poh->size = ivideo->sisfb_heap_size; 3199 poh->offset = ivideo->heapstart; 3200 3201 ivideo->sisfb_heap.oh_free.poh_next = poh; 3202 ivideo->sisfb_heap.oh_free.poh_prev = poh; 3203 ivideo->sisfb_heap.oh_free.size = 0; 3204 ivideo->sisfb_heap.max_freesize = poh->size; 3205 3206 ivideo->sisfb_heap.oh_used.poh_next = &ivideo->sisfb_heap.oh_used; 3207 ivideo->sisfb_heap.oh_used.poh_prev = &ivideo->sisfb_heap.oh_used; 3208 ivideo->sisfb_heap.oh_used.size = SENTINEL; 3209 3210 if(ivideo->cardnumber == 0) { 3211 /* For the first card, make this heap the "global" one 3212 * for old DRM (which could handle only one card) 3213 */ 3214 sisfb_heap = &ivideo->sisfb_heap; 3215 } 3216 3217 return 0; 3218} 3219 3220static struct SIS_OH * 3221sisfb_poh_new_node(struct SIS_HEAP *memheap) 3222{ 3223 struct SIS_OHALLOC *poha; 3224 struct SIS_OH *poh; 3225 unsigned long cOhs; 3226 int i; 3227 3228 if(memheap->poh_freelist == NULL) { 3229 poha = kmalloc(SIS_OH_ALLOC_SIZE, GFP_KERNEL); 3230 if(!poha) 3231 return NULL; 3232 3233 poha->poha_next = memheap->poha_chain; 3234 memheap->poha_chain = poha; 3235 3236 cOhs = (SIS_OH_ALLOC_SIZE - sizeof(struct SIS_OHALLOC)) / sizeof(struct SIS_OH) + 1; 3237 3238 poh = &poha->aoh[0]; 3239 for(i = cOhs - 1; i != 0; i--) { 3240 poh->poh_next = poh + 1; 3241 poh = poh + 1; 3242 } 3243 3244 poh->poh_next = NULL; 3245 memheap->poh_freelist = &poha->aoh[0]; 3246 } 3247 3248 poh = memheap->poh_freelist; 3249 memheap->poh_freelist = poh->poh_next; 3250 3251 return poh; 3252} 3253 3254static struct SIS_OH * 3255sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size) 3256{ 3257 struct SIS_OH *pohThis; 3258 struct SIS_OH *pohRoot; 3259 int bAllocated = 0; 3260 3261 if(size > memheap->max_freesize) { 3262 DPRINTK("sisfb: Can't allocate %dk video memory\n", 3263 (unsigned int) size / 1024); 3264 return NULL; 3265 } 3266 3267 pohThis = memheap->oh_free.poh_next; 3268 3269 while(pohThis != &memheap->oh_free) { 3270 if(size <= pohThis->size) { 3271 bAllocated = 1; 3272 break; 3273 } 3274 pohThis = pohThis->poh_next; 3275 } 3276 3277 if(!bAllocated) { 3278 DPRINTK("sisfb: Can't allocate %dk video memory\n", 3279 (unsigned int) size / 1024); 3280 return NULL; 3281 } 3282 3283 if(size == pohThis->size) { 3284 pohRoot = pohThis; 3285 sisfb_delete_node(pohThis); 3286 } else { 3287 pohRoot = sisfb_poh_new_node(memheap); 3288 if(pohRoot == NULL) 3289 return NULL; 3290 3291 pohRoot->offset = pohThis->offset; 3292 pohRoot->size = size; 3293 3294 pohThis->offset += size; 3295 pohThis->size -= size; 3296 } 3297 3298 memheap->max_freesize -= size; 3299 3300 pohThis = &memheap->oh_used; 3301 sisfb_insert_node(pohThis, pohRoot); 3302 3303 return pohRoot; 3304} 3305 3306static void 3307sisfb_delete_node(struct SIS_OH *poh) 3308{ 3309 poh->poh_prev->poh_next = poh->poh_next; 3310 poh->poh_next->poh_prev = poh->poh_prev; 3311} 3312 3313static void 3314sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh) 3315{ 3316 struct SIS_OH *pohTemp = pohList->poh_next; 3317 3318 pohList->poh_next = poh; 3319 pohTemp->poh_prev = poh; 3320 3321 poh->poh_prev = pohList; 3322 poh->poh_next = pohTemp; 3323} 3324 3325static struct SIS_OH * 3326sisfb_poh_free(struct SIS_HEAP *memheap, u32 base) 3327{ 3328 struct SIS_OH *pohThis; 3329 struct SIS_OH *poh_freed; 3330 struct SIS_OH *poh_prev; 3331 struct SIS_OH *poh_next; 3332 u32 ulUpper; 3333 u32 ulLower; 3334 int foundNode = 0; 3335 3336 poh_freed = memheap->oh_used.poh_next; 3337 3338 while(poh_freed != &memheap->oh_used) { 3339 if(poh_freed->offset == base) { 3340 foundNode = 1; 3341 break; 3342 } 3343 3344 poh_freed = poh_freed->poh_next; 3345 } 3346 3347 if(!foundNode) 3348 return NULL; 3349 3350 memheap->max_freesize += poh_freed->size; 3351 3352 poh_prev = poh_next = NULL; 3353 ulUpper = poh_freed->offset + poh_freed->size; 3354 ulLower = poh_freed->offset; 3355 3356 pohThis = memheap->oh_free.poh_next; 3357 3358 while(pohThis != &memheap->oh_free) { 3359 if(pohThis->offset == ulUpper) { 3360 poh_next = pohThis; 3361 } else if((pohThis->offset + pohThis->size) == ulLower) { 3362 poh_prev = pohThis; 3363 } 3364 pohThis = pohThis->poh_next; 3365 } 3366 3367 sisfb_delete_node(poh_freed); 3368 3369 if(poh_prev && poh_next) { 3370 poh_prev->size += (poh_freed->size + poh_next->size); 3371 sisfb_delete_node(poh_next); 3372 sisfb_free_node(memheap, poh_freed); 3373 sisfb_free_node(memheap, poh_next); 3374 return poh_prev; 3375 } 3376 3377 if(poh_prev) { 3378 poh_prev->size += poh_freed->size; 3379 sisfb_free_node(memheap, poh_freed); 3380 return poh_prev; 3381 } 3382 3383 if(poh_next) { 3384 poh_next->size += poh_freed->size; 3385 poh_next->offset = poh_freed->offset; 3386 sisfb_free_node(memheap, poh_freed); 3387 return poh_next; 3388 } 3389 3390 sisfb_insert_node(&memheap->oh_free, poh_freed); 3391 3392 return poh_freed; 3393} 3394 3395static void 3396sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh) 3397{ 3398 if(poh == NULL) 3399 return; 3400 3401 poh->poh_next = memheap->poh_freelist; 3402 memheap->poh_freelist = poh; 3403} 3404 3405static void 3406sis_int_malloc(struct sis_video_info *ivideo, struct sis_memreq *req) 3407{ 3408 struct SIS_OH *poh = NULL; 3409 3410 if((ivideo) && (ivideo->sisfb_id == SISFB_ID) && (!ivideo->havenoheap)) 3411 poh = sisfb_poh_allocate(&ivideo->sisfb_heap, (u32)req->size); 3412 3413 if(poh == NULL) { 3414 req->offset = req->size = 0; 3415 DPRINTK("sisfb: Video RAM allocation failed\n"); 3416 } else { 3417 req->offset = poh->offset; 3418 req->size = poh->size; 3419 DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n", 3420 (poh->offset + ivideo->video_vbase)); 3421 } 3422} 3423 3424void 3425sis_malloc(struct sis_memreq *req) 3426{ 3427 struct sis_video_info *ivideo = sisfb_heap->vinfo; 3428 3429 if(&ivideo->sisfb_heap == sisfb_heap) 3430 sis_int_malloc(ivideo, req); 3431 else 3432 req->offset = req->size = 0; 3433} 3434 3435void 3436sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req) 3437{ 3438 struct sis_video_info *ivideo = pci_get_drvdata(pdev); 3439 3440 sis_int_malloc(ivideo, req); 3441} 3442 3443/* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */ 3444 3445static void 3446sis_int_free(struct sis_video_info *ivideo, u32 base) 3447{ 3448 struct SIS_OH *poh; 3449 3450 if((!ivideo) || (ivideo->sisfb_id != SISFB_ID) || (ivideo->havenoheap)) 3451 return; 3452 3453 poh = sisfb_poh_free(&ivideo->sisfb_heap, base); 3454 3455 if(poh == NULL) { 3456 DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n", 3457 (unsigned int) base); 3458 } 3459} 3460 3461void 3462sis_free(u32 base) 3463{ 3464 struct sis_video_info *ivideo = sisfb_heap->vinfo; 3465 3466 sis_int_free(ivideo, base); 3467} 3468 3469void 3470sis_free_new(struct pci_dev *pdev, u32 base) 3471{ 3472 struct sis_video_info *ivideo = pci_get_drvdata(pdev); 3473 3474 sis_int_free(ivideo, base); 3475} 3476 3477/* --------------------- SetMode routines ------------------------- */ 3478 3479static void 3480sisfb_check_engine_and_sync(struct sis_video_info *ivideo) 3481{ 3482 u8 cr30, cr31; 3483 3484 /* Check if MMIO and engines are enabled, 3485 * and sync in case they are. Can't use 3486 * ivideo->accel here, as this might have 3487 * been changed before this is called. 3488 */ 3489 inSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, cr30); 3490 inSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, cr31); 3491 /* MMIO and 2D/3D engine enabled? */ 3492 if((cr30 & SIS_MEM_MAP_IO_ENABLE) && (cr31 & 0x42)) { 3493#ifdef CONFIG_FB_SIS_300 3494 if(ivideo->sisvga_engine == SIS_300_VGA) { 3495 /* Don't care about TurboQueue. It's 3496 * enough to know that the engines 3497 * are enabled 3498 */ 3499 sisfb_syncaccel(ivideo); 3500 } 3501#endif 3502#ifdef CONFIG_FB_SIS_315 3503 if(ivideo->sisvga_engine == SIS_315_VGA) { 3504 /* Check that any queue mode is 3505 * enabled, and that the queue 3506 * is not in the state of "reset" 3507 */ 3508 inSISIDXREG(SISSR, 0x26, cr30); 3509 if((cr30 & 0xe0) && (!(cr30 & 0x01))) { 3510 sisfb_syncaccel(ivideo); 3511 } 3512 } 3513#endif 3514 } 3515} 3516 3517static void 3518sisfb_pre_setmode(struct sis_video_info *ivideo) 3519{ 3520 u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0, cr38 = 0; 3521 int tvregnum = 0; 3522 3523 ivideo->currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2); 3524 3525 outSISIDXREG(SISSR, 0x05, 0x86); 3526 3527 inSISIDXREG(SISCR, 0x31, cr31); 3528 cr31 &= ~0x60; 3529 cr31 |= 0x04; 3530 3531 cr33 = ivideo->rate_idx & 0x0F; 3532 3533#ifdef CONFIG_FB_SIS_315 3534 if(ivideo->sisvga_engine == SIS_315_VGA) { 3535 if(ivideo->chip >= SIS_661) { 3536 inSISIDXREG(SISCR, 0x38, cr38); 3537 cr38 &= ~0x07; /* Clear LCDA/DualEdge and YPbPr bits */ 3538 } else { 3539 tvregnum = 0x38; 3540 inSISIDXREG(SISCR, tvregnum, cr38); 3541 cr38 &= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */ 3542 } 3543 } 3544#endif 3545#ifdef CONFIG_FB_SIS_300 3546 if(ivideo->sisvga_engine == SIS_300_VGA) { 3547 tvregnum = 0x35; 3548 inSISIDXREG(SISCR, tvregnum, cr38); 3549 } 3550#endif 3551 3552 SiS_SetEnableDstn(&ivideo->SiS_Pr, false); 3553 SiS_SetEnableFstn(&ivideo->SiS_Pr, false); 3554 ivideo->curFSTN = ivideo->curDSTN = 0; 3555 3556 switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) { 3557 3558 case CRT2_TV: 3559 cr38 &= ~0xc0; /* Clear PAL-M / PAL-N bits */ 3560 if((ivideo->vbflags & TV_YPBPR) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) { 3561#ifdef CONFIG_FB_SIS_315 3562 if(ivideo->chip >= SIS_661) { 3563 cr38 |= 0x04; 3564 if(ivideo->vbflags & TV_YPBPR525P) cr35 |= 0x20; 3565 else if(ivideo->vbflags & TV_YPBPR750P) cr35 |= 0x40; 3566 else if(ivideo->vbflags & TV_YPBPR1080I) cr35 |= 0x60; 3567 cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE; 3568 cr35 &= ~0x01; 3569 ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL)); 3570 } else if(ivideo->sisvga_engine == SIS_315_VGA) { 3571 cr30 |= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE); 3572 cr38 |= 0x08; 3573 if(ivideo->vbflags & TV_YPBPR525P) cr38 |= 0x10; 3574 else if(ivideo->vbflags & TV_YPBPR750P) cr38 |= 0x20; 3575 else if(ivideo->vbflags & TV_YPBPR1080I) cr38 |= 0x30; 3576 cr31 &= ~0x01; 3577 ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL)); 3578 } 3579#endif 3580 } else if((ivideo->vbflags & TV_HIVISION) && 3581 (ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) { 3582 if(ivideo->chip >= SIS_661) { 3583 cr38 |= 0x04; 3584 cr35 |= 0x60; 3585 } else { 3586 cr30 |= 0x80; 3587 } 3588 cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE; 3589 cr31 |= 0x01; 3590 cr35 |= 0x01; 3591 ivideo->currentvbflags |= TV_HIVISION; 3592 } else if(ivideo->vbflags & TV_SCART) { 3593 cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE); 3594 cr31 |= 0x01; 3595 cr35 |= 0x01; 3596 ivideo->currentvbflags |= TV_SCART; 3597 } else { 3598 if(ivideo->vbflags & TV_SVIDEO) { 3599 cr30 = (SIS_VB_OUTPUT_SVIDEO | SIS_SIMULTANEOUS_VIEW_ENABLE); 3600 ivideo->currentvbflags |= TV_SVIDEO; 3601 } 3602 if(ivideo->vbflags & TV_AVIDEO) { 3603 cr30 = (SIS_VB_OUTPUT_COMPOSITE | SIS_SIMULTANEOUS_VIEW_ENABLE); 3604 ivideo->currentvbflags |= TV_AVIDEO; 3605 } 3606 } 3607 cr31 |= SIS_DRIVER_MODE; 3608 3609 if(ivideo->vbflags & (TV_AVIDEO | TV_SVIDEO)) { 3610 if(ivideo->vbflags & TV_PAL) { 3611 cr31 |= 0x01; cr35 |= 0x01; 3612 ivideo->currentvbflags |= TV_PAL; 3613 if(ivideo->vbflags & TV_PALM) { 3614 cr38 |= 0x40; cr35 |= 0x04; 3615 ivideo->currentvbflags |= TV_PALM; 3616 } else if(ivideo->vbflags & TV_PALN) { 3617 cr38 |= 0x80; cr35 |= 0x08; 3618 ivideo->currentvbflags |= TV_PALN; 3619 } 3620 } else { 3621 cr31 &= ~0x01; cr35 &= ~0x01; 3622 ivideo->currentvbflags |= TV_NTSC; 3623 if(ivideo->vbflags & TV_NTSCJ) { 3624 cr38 |= 0x40; cr35 |= 0x02; 3625 ivideo->currentvbflags |= TV_NTSCJ; 3626 } 3627 } 3628 } 3629 break; 3630 3631 case CRT2_LCD: 3632 cr30 = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE); 3633 cr31 |= SIS_DRIVER_MODE; 3634 SiS_SetEnableDstn(&ivideo->SiS_Pr, ivideo->sisfb_dstn); 3635 SiS_SetEnableFstn(&ivideo->SiS_Pr, ivideo->sisfb_fstn); 3636 ivideo->curFSTN = ivideo->sisfb_fstn; 3637 ivideo->curDSTN = ivideo->sisfb_dstn; 3638 break; 3639 3640 case CRT2_VGA: 3641 cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE); 3642 cr31 |= SIS_DRIVER_MODE; 3643 if(ivideo->sisfb_nocrt2rate) { 3644 cr33 |= (sisbios_mode[ivideo->sisfb_mode_idx].rate_idx << 4); 3645 } else { 3646 cr33 |= ((ivideo->rate_idx & 0x0F) << 4); 3647 } 3648 break; 3649 3650 default: /* disable CRT2 */ 3651 cr30 = 0x00; 3652 cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE); 3653 } 3654 3655 outSISIDXREG(SISCR, 0x30, cr30); 3656 outSISIDXREG(SISCR, 0x33, cr33); 3657 3658 if(ivideo->chip >= SIS_661) { 3659#ifdef CONFIG_FB_SIS_315 3660 cr31 &= ~0x01; /* Clear PAL flag (now in CR35) */ 3661 setSISIDXREG(SISCR, 0x35, ~0x10, cr35); /* Leave overscan bit alone */ 3662 cr38 &= 0x07; /* Use only LCDA and HiVision/YPbPr bits */ 3663 setSISIDXREG(SISCR, 0x38, 0xf8, cr38); 3664#endif 3665 } else if(ivideo->chip != SIS_300) { 3666 outSISIDXREG(SISCR, tvregnum, cr38); 3667 } 3668 outSISIDXREG(SISCR, 0x31, cr31); 3669 3670 ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem; 3671 3672 sisfb_check_engine_and_sync(ivideo); 3673} 3674 3675/* Fix SR11 for 661 and later */ 3676#ifdef CONFIG_FB_SIS_315 3677static void 3678sisfb_fixup_SR11(struct sis_video_info *ivideo) 3679{ 3680 u8 tmpreg; 3681 3682 if(ivideo->chip >= SIS_661) { 3683 inSISIDXREG(SISSR,0x11,tmpreg); 3684 if(tmpreg & 0x20) { 3685 inSISIDXREG(SISSR,0x3e,tmpreg); 3686 tmpreg = (tmpreg + 1) & 0xff; 3687 outSISIDXREG(SISSR,0x3e,tmpreg); 3688 inSISIDXREG(SISSR,0x11,tmpreg); 3689 } 3690 if(tmpreg & 0xf0) { 3691 andSISIDXREG(SISSR,0x11,0x0f); 3692 } 3693 } 3694} 3695#endif 3696 3697static void 3698sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val) 3699{ 3700 if(val > 32) val = 32; 3701 if(val < -32) val = -32; 3702 ivideo->tvxpos = val; 3703 3704 if(ivideo->sisfblocked) return; 3705 if(!ivideo->modechanged) return; 3706 3707 if(ivideo->currentvbflags & CRT2_TV) { 3708 3709 if(ivideo->vbflags2 & VB2_CHRONTEL) { 3710 3711 int x = ivideo->tvx; 3712 3713 switch(ivideo->chronteltype) { 3714 case 1: 3715 x += val; 3716 if(x < 0) x = 0; 3717 outSISIDXREG(SISSR,0x05,0x86); 3718 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0a, (x & 0xff)); 3719 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((x & 0x0100) >> 7), 0xFD); 3720 break; 3721 case 2: 3722 /* Not supported by hardware */ 3723 break; 3724 } 3725 3726 } else if(ivideo->vbflags2 & VB2_SISBRIDGE) { 3727 3728 u8 p2_1f,p2_20,p2_2b,p2_42,p2_43; 3729 unsigned short temp; 3730 3731 p2_1f = ivideo->p2_1f; 3732 p2_20 = ivideo->p2_20; 3733 p2_2b = ivideo->p2_2b; 3734 p2_42 = ivideo->p2_42; 3735 p2_43 = ivideo->p2_43; 3736 3737 temp = p2_1f | ((p2_20 & 0xf0) << 4); 3738 temp += (val * 2); 3739 p2_1f = temp & 0xff; 3740 p2_20 = (temp & 0xf00) >> 4; 3741 p2_2b = ((p2_2b & 0x0f) + (val * 2)) & 0x0f; 3742 temp = p2_43 | ((p2_42 & 0xf0) << 4); 3743 temp += (val * 2); 3744 p2_43 = temp & 0xff; 3745 p2_42 = (temp & 0xf00) >> 4; 3746 outSISIDXREG(SISPART2,0x1f,p2_1f); 3747 setSISIDXREG(SISPART2,0x20,0x0F,p2_20); 3748 setSISIDXREG(SISPART2,0x2b,0xF0,p2_2b); 3749 setSISIDXREG(SISPART2,0x42,0x0F,p2_42); 3750 outSISIDXREG(SISPART2,0x43,p2_43); 3751 } 3752 } 3753} 3754 3755static void 3756sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val) 3757{ 3758 if(val > 32) val = 32; 3759 if(val < -32) val = -32; 3760 ivideo->tvypos = val; 3761 3762 if(ivideo->sisfblocked) return; 3763 if(!ivideo->modechanged) return; 3764 3765 if(ivideo->currentvbflags & CRT2_TV) { 3766 3767 if(ivideo->vbflags2 & VB2_CHRONTEL) { 3768 3769 int y = ivideo->tvy; 3770 3771 switch(ivideo->chronteltype) { 3772 case 1: 3773 y -= val; 3774 if(y < 0) y = 0; 3775 outSISIDXREG(SISSR,0x05,0x86); 3776 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b, (y & 0xff)); 3777 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((y & 0x0100) >> 8), 0xFE); 3778 break; 3779 case 2: 3780 /* Not supported by hardware */ 3781 break; 3782 } 3783 3784 } else if(ivideo->vbflags2 & VB2_SISBRIDGE) { 3785 3786 char p2_01, p2_02; 3787 val /= 2; 3788 p2_01 = ivideo->p2_01; 3789 p2_02 = ivideo->p2_02; 3790 3791 p2_01 += val; 3792 p2_02 += val; 3793 if(!(ivideo->currentvbflags & (TV_HIVISION | TV_YPBPR))) { 3794 while((p2_01 <= 0) || (p2_02 <= 0)) { 3795 p2_01 += 2; 3796 p2_02 += 2; 3797 } 3798 } 3799 outSISIDXREG(SISPART2,0x01,p2_01); 3800 outSISIDXREG(SISPART2,0x02,p2_02); 3801 } 3802 } 3803} 3804 3805static void 3806sisfb_post_setmode(struct sis_video_info *ivideo) 3807{ 3808 bool crt1isoff = false; 3809 bool doit = true; 3810#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315) 3811 u8 reg; 3812#endif 3813#ifdef CONFIG_FB_SIS_315 3814 u8 reg1; 3815#endif 3816 3817 outSISIDXREG(SISSR, 0x05, 0x86); 3818 3819#ifdef CONFIG_FB_SIS_315 3820 sisfb_fixup_SR11(ivideo); 3821#endif 3822 3823 /* Now we actually HAVE changed the display mode */ 3824 ivideo->modechanged = 1; 3825 3826 /* We can't switch off CRT1 if bridge is in slave mode */ 3827 if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) { 3828 if(sisfb_bridgeisslave(ivideo)) doit = false; 3829 } else 3830 ivideo->sisfb_crt1off = 0; 3831 3832#ifdef CONFIG_FB_SIS_300 3833 if(ivideo->sisvga_engine == SIS_300_VGA) { 3834 if((ivideo->sisfb_crt1off) && (doit)) { 3835 crt1isoff = true; 3836 reg = 0x00; 3837 } else { 3838 crt1isoff = false; 3839 reg = 0x80; 3840 } 3841 setSISIDXREG(SISCR, 0x17, 0x7f, reg); 3842 } 3843#endif 3844#ifdef CONFIG_FB_SIS_315 3845 if(ivideo->sisvga_engine == SIS_315_VGA) { 3846 if((ivideo->sisfb_crt1off) && (doit)) { 3847 crt1isoff = true; 3848 reg = 0x40; 3849 reg1 = 0xc0; 3850 } else { 3851 crt1isoff = false; 3852 reg = 0x00; 3853 reg1 = 0x00; 3854 } 3855 setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg); 3856 setSISIDXREG(SISSR, 0x1f, ~0xc0, reg1); 3857 } 3858#endif 3859 3860 if(crt1isoff) { 3861 ivideo->currentvbflags &= ~VB_DISPTYPE_CRT1; 3862 ivideo->currentvbflags |= VB_SINGLE_MODE; 3863 } else { 3864 ivideo->currentvbflags |= VB_DISPTYPE_CRT1; 3865 if(ivideo->currentvbflags & VB_DISPTYPE_CRT2) { 3866 ivideo->currentvbflags |= VB_MIRROR_MODE; 3867 } else { 3868 ivideo->currentvbflags |= VB_SINGLE_MODE; 3869 } 3870 } 3871 3872 andSISIDXREG(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04); 3873 3874 if(ivideo->currentvbflags & CRT2_TV) { 3875 if(ivideo->vbflags2 & VB2_SISBRIDGE) { 3876 inSISIDXREG(SISPART2,0x1f,ivideo->p2_1f); 3877 inSISIDXREG(SISPART2,0x20,ivideo->p2_20); 3878 inSISIDXREG(SISPART2,0x2b,ivideo->p2_2b); 3879 inSISIDXREG(SISPART2,0x42,ivideo->p2_42); 3880 inSISIDXREG(SISPART2,0x43,ivideo->p2_43); 3881 inSISIDXREG(SISPART2,0x01,ivideo->p2_01); 3882 inSISIDXREG(SISPART2,0x02,ivideo->p2_02); 3883 } else if(ivideo->vbflags2 & VB2_CHRONTEL) { 3884 if(ivideo->chronteltype == 1) { 3885 ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a); 3886 ivideo->tvx |= (((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x02) >> 1) << 8); 3887 ivideo->tvy = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0b); 3888 ivideo->tvy |= ((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x01) << 8); 3889 } 3890 } 3891 } 3892 3893 if(ivideo->tvxpos) { 3894 sisfb_set_TVxposoffset(ivideo, ivideo->tvxpos); 3895 } 3896 if(ivideo->tvypos) { 3897 sisfb_set_TVyposoffset(ivideo, ivideo->tvypos); 3898 } 3899 3900 /* Eventually sync engines */ 3901 sisfb_check_engine_and_sync(ivideo); 3902 3903 /* (Re-)Initialize chip engines */ 3904 if(ivideo->accel) { 3905 sisfb_engine_init(ivideo); 3906 } else { 3907 ivideo->engineok = 0; 3908 } 3909} 3910 3911static int 3912sisfb_reset_mode(struct sis_video_info *ivideo) 3913{ 3914 if(sisfb_set_mode(ivideo, 0)) 3915 return 1; 3916 3917 sisfb_set_pitch(ivideo); 3918 sisfb_set_base_CRT1(ivideo, ivideo->current_base); 3919 sisfb_set_base_CRT2(ivideo, ivideo->current_base); 3920 3921 return 0; 3922} 3923 3924static void 3925sisfb_handle_command(struct sis_video_info *ivideo, struct sisfb_cmd *sisfb_command) 3926{ 3927 int mycrt1off; 3928 3929 switch(sisfb_command->sisfb_cmd) { 3930 case SISFB_CMD_GETVBFLAGS: 3931 if(!ivideo->modechanged) { 3932 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY; 3933 } else { 3934 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK; 3935 sisfb_command->sisfb_result[1] = ivideo->currentvbflags; 3936 sisfb_command->sisfb_result[2] = ivideo->vbflags2; 3937 } 3938 break; 3939 case SISFB_CMD_SWITCHCRT1: 3940 /* arg[0]: 0 = off, 1 = on, 99 = query */ 3941 if(!ivideo->modechanged) { 3942 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY; 3943 } else if(sisfb_command->sisfb_arg[0] == 99) { 3944 /* Query */ 3945 sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1; 3946 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK; 3947 } else if(ivideo->sisfblocked) { 3948 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_LOCKED; 3949 } else if((!(ivideo->currentvbflags & CRT2_ENABLE)) && 3950 (sisfb_command->sisfb_arg[0] == 0)) { 3951 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_NOCRT2; 3952 } else { 3953 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK; 3954 mycrt1off = sisfb_command->sisfb_arg[0] ? 0 : 1; 3955 if( ((ivideo->currentvbflags & VB_DISPTYPE_CRT1) && mycrt1off) || 3956 ((!(ivideo->currentvbflags & VB_DISPTYPE_CRT1)) && !mycrt1off) ) { 3957 ivideo->sisfb_crt1off = mycrt1off; 3958 if(sisfb_reset_mode(ivideo)) { 3959 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OTHER; 3960 } 3961 } 3962 sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1; 3963 } 3964 break; 3965 /* more to come */ 3966 default: 3967 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_UNKNOWN; 3968 printk(KERN_ERR "sisfb: Unknown command 0x%x\n", 3969 sisfb_command->sisfb_cmd); 3970 } 3971} 3972 3973#ifndef MODULE 3974SISINITSTATIC int __init 3975sisfb_setup(char *options) 3976{ 3977 char *this_opt; 3978 3979 sisfb_setdefaultparms(); 3980 3981 if(!options || !(*options)) 3982 return 0; 3983 3984 while((this_opt = strsep(&options, ",")) != NULL) { 3985 3986 if(!(*this_opt)) continue; 3987 3988 if(!strnicmp(this_opt, "off", 3)) { 3989 sisfb_off = 1; 3990 } else if(!strnicmp(this_opt, "forcecrt2type:", 14)) { 3991 /* Need to check crt2 type first for fstn/dstn */ 3992 sisfb_search_crt2type(this_opt + 14); 3993 } else if(!strnicmp(this_opt, "tvmode:",7)) { 3994 sisfb_search_tvstd(this_opt + 7); 3995 } else if(!strnicmp(this_opt, "tvstandard:",11)) { 3996 sisfb_search_tvstd(this_opt + 11); 3997 } else if(!strnicmp(this_opt, "mode:", 5)) { 3998 sisfb_search_mode(this_opt + 5, false); 3999 } else if(!strnicmp(this_opt, "vesa:", 5)) { 4000 sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), false); 4001 } else if(!strnicmp(this_opt, "rate:", 5)) { 4002 sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0); 4003 } else if(!strnicmp(this_opt, "forcecrt1:", 10)) { 4004 sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0); 4005 } else if(!strnicmp(this_opt, "mem:",4)) { 4006 sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0); 4007 } else if(!strnicmp(this_opt, "pdc:", 4)) { 4008 sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0); 4009 } else if(!strnicmp(this_opt, "pdc1:", 5)) { 4010 sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0); 4011 } else if(!strnicmp(this_opt, "noaccel", 7)) { 4012 sisfb_accel = 0; 4013 } else if(!strnicmp(this_opt, "accel", 5)) { 4014 sisfb_accel = -1; 4015 } else if(!strnicmp(this_opt, "noypan", 6)) { 4016 sisfb_ypan = 0; 4017 } else if(!strnicmp(this_opt, "ypan", 4)) { 4018 sisfb_ypan = -1; 4019 } else if(!strnicmp(this_opt, "nomax", 5)) { 4020 sisfb_max = 0; 4021 } else if(!strnicmp(this_opt, "max", 3)) { 4022 sisfb_max = -1; 4023 } else if(!strnicmp(this_opt, "userom:", 7)) { 4024 sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0); 4025 } else if(!strnicmp(this_opt, "useoem:", 7)) { 4026 sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0); 4027 } else if(!strnicmp(this_opt, "nocrt2rate", 10)) { 4028 sisfb_nocrt2rate = 1; 4029 } else if(!strnicmp(this_opt, "scalelcd:", 9)) { 4030 unsigned long temp = 2; 4031 temp = simple_strtoul(this_opt + 9, NULL, 0); 4032 if((temp == 0) || (temp == 1)) { 4033 sisfb_scalelcd = temp ^ 1; 4034 } 4035 } else if(!strnicmp(this_opt, "tvxposoffset:", 13)) { 4036 int temp = 0; 4037 temp = (int)simple_strtol(this_opt + 13, NULL, 0); 4038 if((temp >= -32) && (temp <= 32)) { 4039 sisfb_tvxposoffset = temp; 4040 } 4041 } else if(!strnicmp(this_opt, "tvyposoffset:", 13)) { 4042 int temp = 0; 4043 temp = (int)simple_strtol(this_opt + 13, NULL, 0); 4044 if((temp >= -32) && (temp <= 32)) { 4045 sisfb_tvyposoffset = temp; 4046 } 4047 } else if(!strnicmp(this_opt, "specialtiming:", 14)) { 4048 sisfb_search_specialtiming(this_opt + 14); 4049 } else if(!strnicmp(this_opt, "lvdshl:", 7)) { 4050 int temp = 4; 4051 temp = simple_strtoul(this_opt + 7, NULL, 0); 4052 if((temp >= 0) && (temp <= 3)) { 4053 sisfb_lvdshl = temp; 4054 } 4055 } else if(this_opt[0] >= '0' && this_opt[0] <= '9') { 4056 sisfb_search_mode(this_opt, true); 4057#if !defined(__i386__) && !defined(__x86_64__) 4058 } else if(!strnicmp(this_opt, "resetcard", 9)) { 4059 sisfb_resetcard = 1; 4060 } else if(!strnicmp(this_opt, "videoram:", 9)) { 4061 sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0); 4062#endif 4063 } else { 4064 printk(KERN_INFO "sisfb: Invalid option %s\n", this_opt); 4065 } 4066 4067 } 4068 4069 return 0; 4070} 4071#endif 4072 4073static int __devinit 4074sisfb_check_rom(SIS_IOTYPE1 *rom_base, struct sis_video_info *ivideo) 4075{ 4076 SIS_IOTYPE1 *rom; 4077 int romptr; 4078 4079 if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa)) 4080 return 0; 4081 4082 romptr = (readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8)); 4083 if(romptr > (0x10000 - 8)) 4084 return 0; 4085 4086 rom = rom_base + romptr; 4087 4088 if((readb(rom) != 'P') || (readb(rom + 1) != 'C') || 4089 (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R')) 4090 return 0; 4091 4092 if((readb(rom + 4) | (readb(rom + 5) << 8)) != ivideo->chip_vendor) 4093 return 0; 4094 4095 if((readb(rom + 6) | (readb(rom + 7) << 8)) != ivideo->chip_id) 4096 return 0; 4097 4098 return 1; 4099} 4100 4101static unsigned char * __devinit 4102sisfb_find_rom(struct pci_dev *pdev) 4103{ 4104 struct sis_video_info *ivideo = pci_get_drvdata(pdev); 4105 SIS_IOTYPE1 *rom_base; 4106 unsigned char *myrombase = NULL; 4107 u32 temp; 4108#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) 4109 size_t romsize; 4110 4111 /* First, try the official pci ROM functions (except 4112 * on integrated chipsets which have no ROM). 4113 */ 4114 4115 if(!ivideo->nbridge) { 4116 4117 if((rom_base = pci_map_rom(pdev, &romsize))) { 4118 4119 if(sisfb_check_rom(rom_base, ivideo)) { 4120 4121 if((myrombase = vmalloc(65536))) { 4122 4123 if(pci_resource_len(pdev, PCI_ROM_RESOURCE) < romsize) 4124 romsize = pci_resource_len(pdev, PCI_ROM_RESOURCE); 4125 4126 memcpy_fromio(myrombase, rom_base, 4127 (romsize > 65536) ? 65536 : romsize); 4128 } 4129 } 4130 pci_unmap_rom(pdev, rom_base); 4131 } 4132 } 4133 4134 if(myrombase) return myrombase; 4135#endif 4136 4137 /* Otherwise do it the conventional way. */ 4138 4139#if defined(__i386__) || defined(__x86_64__) 4140 4141 for(temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) { 4142 4143 rom_base = ioremap(temp, 65536); 4144 if(!rom_base) 4145 continue; 4146 4147 if(!sisfb_check_rom(rom_base, ivideo)) { 4148 iounmap(rom_base); 4149 continue; 4150 } 4151 4152 if((myrombase = vmalloc(65536))) 4153 memcpy_fromio(myrombase, rom_base, 65536); 4154 4155 iounmap(rom_base); 4156 break; 4157 4158 } 4159 4160#else 4161 4162 pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &temp); 4163 pci_write_config_dword(pdev, PCI_ROM_ADDRESS, 4164 (ivideo->video_base & PCI_ROM_ADDRESS_MASK) | PCI_ROM_ADDRESS_ENABLE); 4165 4166 rom_base = ioremap(ivideo->video_base, 65536); 4167 if(rom_base) { 4168 if(sisfb_check_rom(rom_base, ivideo)) { 4169 if((myrombase = vmalloc(65536))) 4170 memcpy_fromio(myrombase, rom_base, 65536); 4171 } 4172 iounmap(rom_base); 4173 } 4174 4175 pci_write_config_dword(pdev, PCI_ROM_ADDRESS, temp); 4176 4177#endif 4178 4179 return myrombase; 4180} 4181 4182static void __devinit 4183sisfb_post_map_vram(struct sis_video_info *ivideo, unsigned int *mapsize, 4184 unsigned int min) 4185{ 4186 ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize)); 4187 4188 if(!ivideo->video_vbase) { 4189 printk(KERN_ERR 4190 "sisfb: Unable to map maximum video RAM for size detection\n"); 4191 (*mapsize) >>= 1; 4192 while((!(ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize))))) { 4193 (*mapsize) >>= 1; 4194 if((*mapsize) < (min << 20)) 4195 break; 4196 } 4197 if(ivideo->video_vbase) { 4198 printk(KERN_ERR 4199 "sisfb: Video RAM size detection limited to %dMB\n", 4200 (int)((*mapsize) >> 20)); 4201 } 4202 } 4203} 4204 4205#ifdef CONFIG_FB_SIS_300 4206static int __devinit 4207sisfb_post_300_buswidth(struct sis_video_info *ivideo) 4208{ 4209 SIS_IOTYPE1 *FBAddress = ivideo->video_vbase; 4210 unsigned short temp; 4211 unsigned char reg; 4212 int i, j; 4213 4214 andSISIDXREG(SISSR, 0x15, 0xFB); 4215 orSISIDXREG(SISSR, 0x15, 0x04); 4216 outSISIDXREG(SISSR, 0x13, 0x00); 4217 outSISIDXREG(SISSR, 0x14, 0xBF); 4218 4219 for(i = 0; i < 2; i++) { 4220 temp = 0x1234; 4221 for(j = 0; j < 4; j++) { 4222 writew(temp, FBAddress); 4223 if(readw(FBAddress) == temp) 4224 break; 4225 orSISIDXREG(SISSR, 0x3c, 0x01); 4226 inSISIDXREG(SISSR, 0x05, reg); 4227 inSISIDXREG(SISSR, 0x05, reg); 4228 andSISIDXREG(SISSR, 0x3c, 0xfe); 4229 inSISIDXREG(SISSR, 0x05, reg); 4230 inSISIDXREG(SISSR, 0x05, reg); 4231 temp++; 4232 } 4233 } 4234 4235 writel(0x01234567L, FBAddress); 4236 writel(0x456789ABL, (FBAddress + 4)); 4237 writel(0x89ABCDEFL, (FBAddress + 8)); 4238 writel(0xCDEF0123L, (FBAddress + 12)); 4239 4240 inSISIDXREG(SISSR, 0x3b, reg); 4241 if(reg & 0x01) { 4242 if(readl((FBAddress + 12)) == 0xCDEF0123L) 4243 return 4; /* Channel A 128bit */ 4244 } 4245 4246 if(readl((FBAddress + 4)) == 0x456789ABL) 4247 return 2; /* Channel B 64bit */ 4248 4249 return 1; /* 32bit */ 4250} 4251 4252static int __devinit 4253sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration, int buswidth, 4254 int PseudoRankCapacity, int PseudoAdrPinCount, 4255 unsigned int mapsize) 4256{ 4257 SIS_IOTYPE1 *FBAddr = ivideo->video_vbase; 4258 unsigned short sr14; 4259 unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid; 4260 unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage; 4261 static const unsigned short SiS_DRAMType[17][5] = { 4262 {0x0C,0x0A,0x02,0x40,0x39}, 4263 {0x0D,0x0A,0x01,0x40,0x48}, 4264 {0x0C,0x09,0x02,0x20,0x35}, 4265 {0x0D,0x09,0x01,0x20,0x44}, 4266 {0x0C,0x08,0x02,0x10,0x31}, 4267 {0x0D,0x08,0x01,0x10,0x40}, 4268 {0x0C,0x0A,0x01,0x20,0x34}, 4269 {0x0C,0x09,0x01,0x08,0x32}, 4270 {0x0B,0x08,0x02,0x08,0x21}, 4271 {0x0C,0x08,0x01,0x08,0x30}, 4272 {0x0A,0x08,0x02,0x04,0x11}, 4273 {0x0B,0x0A,0x01,0x10,0x28}, 4274 {0x09,0x08,0x02,0x02,0x01}, 4275 {0x0B,0x09,0x01,0x08,0x24}, 4276 {0x0B,0x08,0x01,0x04,0x20}, 4277 {0x0A,0x08,0x01,0x02,0x10}, 4278 {0x09,0x08,0x01,0x01,0x00} 4279 }; 4280 4281 for(k = 0; k <= 16; k++) { 4282 4283 RankCapacity = buswidth * SiS_DRAMType[k][3]; 4284 4285 if(RankCapacity != PseudoRankCapacity) 4286 continue; 4287 4288 if((SiS_DRAMType[k][2] + SiS_DRAMType[k][0]) > PseudoAdrPinCount) 4289 continue; 4290 4291 BankNumHigh = RankCapacity * 16 * iteration - 1; 4292 if(iteration == 3) { /* Rank No */ 4293 BankNumMid = RankCapacity * 16 - 1; 4294 } else { 4295 BankNumMid = RankCapacity * 16 * iteration / 2 - 1; 4296 } 4297 4298 PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4; 4299 PhysicalAdrHigh = BankNumHigh; 4300 PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity; 4301 PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh; 4302 4303 andSISIDXREG(SISSR, 0x15, 0xFB); /* Test */ 4304 orSISIDXREG(SISSR, 0x15, 0x04); /* Test */ 4305 sr14 = (SiS_DRAMType[k][3] * buswidth) - 1; 4306 if(buswidth == 4) sr14 |= 0x80; 4307 else if(buswidth == 2) sr14 |= 0x40; 4308 outSISIDXREG(SISSR, 0x13, SiS_DRAMType[k][4]); 4309 outSISIDXREG(SISSR, 0x14, sr14); 4310 4311 BankNumHigh <<= 16; 4312 BankNumMid <<= 16; 4313 4314 if((BankNumHigh + PhysicalAdrHigh >= mapsize) || 4315 (BankNumMid + PhysicalAdrHigh >= mapsize) || 4316 (BankNumHigh + PhysicalAdrHalfPage >= mapsize) || 4317 (BankNumHigh + PhysicalAdrOtherPage >= mapsize)) 4318 continue; 4319 4320 /* Write data */ 4321 writew(((unsigned short)PhysicalAdrHigh), 4322 (FBAddr + BankNumHigh + PhysicalAdrHigh)); 4323 writew(((unsigned short)BankNumMid), 4324 (FBAddr + BankNumMid + PhysicalAdrHigh)); 4325 writew(((unsigned short)PhysicalAdrHalfPage), 4326 (FBAddr + BankNumHigh + PhysicalAdrHalfPage)); 4327 writew(((unsigned short)PhysicalAdrOtherPage), 4328 (FBAddr + BankNumHigh + PhysicalAdrOtherPage)); 4329 4330 /* Read data */ 4331 if(readw(FBAddr + BankNumHigh + PhysicalAdrHigh) == PhysicalAdrHigh) 4332 return 1; 4333 } 4334 4335 return 0; 4336} 4337 4338static void __devinit 4339sisfb_post_300_ramsize(struct pci_dev *pdev, unsigned int mapsize) 4340{ 4341 struct sis_video_info *ivideo = pci_get_drvdata(pdev); 4342 int i, j, buswidth; 4343 int PseudoRankCapacity, PseudoAdrPinCount; 4344 4345 buswidth = sisfb_post_300_buswidth(ivideo); 4346 4347 for(i = 6; i >= 0; i--) { 4348 PseudoRankCapacity = 1 << i; 4349 for(j = 4; j >= 1; j--) { 4350 PseudoAdrPinCount = 15 - j; 4351 if((PseudoRankCapacity * j) <= 64) { 4352 if(sisfb_post_300_rwtest(ivideo, 4353 j, 4354 buswidth, 4355 PseudoRankCapacity, 4356 PseudoAdrPinCount, 4357 mapsize)) 4358 return; 4359 } 4360 } 4361 } 4362} 4363 4364static void __devinit 4365sisfb_post_sis300(struct pci_dev *pdev) 4366{ 4367 struct sis_video_info *ivideo = pci_get_drvdata(pdev); 4368 unsigned char *bios = ivideo->SiS_Pr.VirtualRomBase; 4369 u8 reg, v1, v2, v3, v4, v5, v6, v7, v8; 4370 u16 index, rindex, memtype = 0; 4371 unsigned int mapsize; 4372 4373 if(!ivideo->SiS_Pr.UseROM) 4374 bios = NULL; 4375 4376 outSISIDXREG(SISSR, 0x05, 0x86); 4377 4378 if(bios) { 4379 if(bios[0x52] & 0x80) { 4380 memtype = bios[0x52]; 4381 } else { 4382 inSISIDXREG(SISSR, 0x3a, memtype); 4383 } 4384 memtype &= 0x07; 4385 } 4386 4387 v3 = 0x80; v6 = 0x80; 4388 if(ivideo->revision_id <= 0x13) { 4389 v1 = 0x44; v2 = 0x42; 4390 v4 = 0x44; v5 = 0x42; 4391 } else { 4392 v1 = 0x68; v2 = 0x43; /* Assume 125Mhz MCLK */ 4393 v4 = 0x68; v5 = 0x43; /* Assume 125Mhz ECLK */ 4394 if(bios) { 4395 index = memtype * 5; 4396 rindex = index + 0x54; 4397 v1 = bios[rindex++]; 4398 v2 = bios[rindex++]; 4399 v3 = bios[rindex++]; 4400 rindex = index + 0x7c; 4401 v4 = bios[rindex++]; 4402 v5 = bios[rindex++]; 4403 v6 = bios[rindex++]; 4404 } 4405 } 4406 outSISIDXREG(SISSR, 0x28, v1); 4407 outSISIDXREG(SISSR, 0x29, v2); 4408 outSISIDXREG(SISSR, 0x2a, v3); 4409 outSISIDXREG(SISSR, 0x2e, v4); 4410 outSISIDXREG(SISSR, 0x2f, v5); 4411 outSISIDXREG(SISSR, 0x30, v6); 4412 4413 v1 = 0x10; 4414 if(bios) 4415 v1 = bios[0xa4]; 4416 outSISIDXREG(SISSR, 0x07, v1); /* DAC speed */ 4417 4418 outSISIDXREG(SISSR, 0x11, 0x0f); /* DDC, power save */ 4419 4420 v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a; 4421 v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00; 4422 if(bios) { 4423 memtype += 0xa5; 4424 v1 = bios[memtype]; 4425 v2 = bios[memtype + 8]; 4426 v3 = bios[memtype + 16]; 4427 v4 = bios[memtype + 24]; 4428 v5 = bios[memtype + 32]; 4429 v6 = bios[memtype + 40]; 4430 v7 = bios[memtype + 48]; 4431 v8 = bios[memtype + 56]; 4432 } 4433 if(ivideo->revision_id >= 0x80) 4434 v3 &= 0xfd; 4435 outSISIDXREG(SISSR, 0x15, v1); /* Ram type (assuming 0, BIOS 0xa5 step 8) */ 4436 outSISIDXREG(SISSR, 0x16, v2); 4437 outSISIDXREG(SISSR, 0x17, v3); 4438 outSISIDXREG(SISSR, 0x18, v4); 4439 outSISIDXREG(SISSR, 0x19, v5); 4440 outSISIDXREG(SISSR, 0x1a, v6); 4441 outSISIDXREG(SISSR, 0x1b, v7); 4442 outSISIDXREG(SISSR, 0x1c, v8); /* ---- */ 4443 andSISIDXREG(SISSR, 0x15 ,0xfb); 4444 orSISIDXREG(SISSR, 0x15, 0x04); 4445 if(bios) { 4446 if(bios[0x53] & 0x02) { 4447 orSISIDXREG(SISSR, 0x19, 0x20); 4448 } 4449 } 4450 v1 = 0x04; /* DAC pedestal (BIOS 0xe5) */ 4451 if(ivideo->revision_id >= 0x80) 4452 v1 |= 0x01; 4453 outSISIDXREG(SISSR, 0x1f, v1); 4454 outSISIDXREG(SISSR, 0x20, 0xa4); /* linear & relocated io & disable a0000 */ 4455 v1 = 0xf6; v2 = 0x0d; v3 = 0x00; 4456 if(bios) { 4457 v1 = bios[0xe8]; 4458 v2 = bios[0xe9]; 4459 v3 = bios[0xea]; 4460 } 4461 outSISIDXREG(SISSR, 0x23, v1); 4462 outSISIDXREG(SISSR, 0x24, v2); 4463 outSISIDXREG(SISSR, 0x25, v3); 4464 outSISIDXREG(SISSR, 0x21, 0x84); 4465 outSISIDXREG(SISSR, 0x22, 0x00); 4466 outSISIDXREG(SISCR, 0x37, 0x00); 4467 orSISIDXREG(SISPART1, 0x24, 0x01); /* unlock crt2 */ 4468 outSISIDXREG(SISPART1, 0x00, 0x00); 4469 v1 = 0x40; v2 = 0x11; 4470 if(bios) { 4471 v1 = bios[0xec]; 4472 v2 = bios[0xeb]; 4473 } 4474 outSISIDXREG(SISPART1, 0x02, v1); 4475 4476 if(ivideo->revision_id >= 0x80) 4477 v2 &= ~0x01; 4478 4479 inSISIDXREG(SISPART4, 0x00, reg); 4480 if((reg == 1) || (reg == 2)) { 4481 outSISIDXREG(SISCR, 0x37, 0x02); 4482 outSISIDXREG(SISPART2, 0x00, 0x1c); 4483 v4 = 0x00; v5 = 0x00; v6 = 0x10; 4484 if(ivideo->SiS_Pr.UseROM) { 4485 v4 = bios[0xf5]; 4486 v5 = bios[0xf6]; 4487 v6 = bios[0xf7]; 4488 } 4489 outSISIDXREG(SISPART4, 0x0d, v4); 4490 outSISIDXREG(SISPART4, 0x0e, v5); 4491 outSISIDXREG(SISPART4, 0x10, v6); 4492 outSISIDXREG(SISPART4, 0x0f, 0x3f); 4493 inSISIDXREG(SISPART4, 0x01, reg); 4494 if(reg >= 0xb0) { 4495 inSISIDXREG(SISPART4, 0x23, reg); 4496 reg &= 0x20; 4497 reg <<= 1; 4498 outSISIDXREG(SISPART4, 0x23, reg); 4499 } 4500 } else { 4501 v2 &= ~0x10; 4502 } 4503 outSISIDXREG(SISSR, 0x32, v2); 4504 4505 andSISIDXREG(SISPART1, 0x24, 0xfe); /* Lock CRT2 */ 4506 4507 inSISIDXREG(SISSR, 0x16, reg); 4508 reg &= 0xc3; 4509 outSISIDXREG(SISCR, 0x35, reg); 4510 outSISIDXREG(SISCR, 0x83, 0x00); 4511#if !defined(__i386__) && !defined(__x86_64__) 4512 if(sisfb_videoram) { 4513 outSISIDXREG(SISSR, 0x13, 0x28); /* ? */ 4514 reg = ((sisfb_videoram >> 10) - 1) | 0x40; 4515 outSISIDXREG(SISSR, 0x14, reg); 4516 } else { 4517#endif 4518 /* Need to map max FB size for finding out about RAM size */ 4519 mapsize = 64 << 20; 4520 sisfb_post_map_vram(ivideo, &mapsize, 4); 4521 4522 if(ivideo->video_vbase) { 4523 sisfb_post_300_ramsize(pdev, mapsize); 4524 iounmap(ivideo->video_vbase); 4525 } else { 4526 printk(KERN_DEBUG 4527 "sisfb: Failed to map memory for size detection, assuming 8MB\n"); 4528 outSISIDXREG(SISSR, 0x13, 0x28); /* ? */ 4529 outSISIDXREG(SISSR, 0x14, 0x47); /* 8MB, 64bit default */ 4530 } 4531#if !defined(__i386__) && !defined(__x86_64__) 4532 } 4533#endif 4534 if(bios) { 4535 v1 = bios[0xe6]; 4536 v2 = bios[0xe7]; 4537 } else { 4538 inSISIDXREG(SISSR, 0x3a, reg); 4539 if((reg & 0x30) == 0x30) { 4540 v1 = 0x04; /* PCI */ 4541 v2 = 0x92; 4542 } else { 4543 v1 = 0x14; /* AGP */ 4544 v2 = 0xb2; 4545 } 4546 } 4547 outSISIDXREG(SISSR, 0x21, v1); 4548 outSISIDXREG(SISSR, 0x22, v2); 4549 4550 /* Sense CRT1 */ 4551 sisfb_sense_crt1(ivideo); 4552 4553 /* Set default mode, don't clear screen */ 4554 ivideo->SiS_Pr.SiS_UseOEM = false; 4555 SiS_SetEnableDstn(&ivideo->SiS_Pr, false); 4556 SiS_SetEnableFstn(&ivideo->SiS_Pr, false); 4557 ivideo->curFSTN = ivideo->curDSTN = 0; 4558 ivideo->SiS_Pr.VideoMemorySize = 8 << 20; 4559 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80); 4560 4561 outSISIDXREG(SISSR, 0x05, 0x86); 4562 4563 /* Display off */ 4564 orSISIDXREG(SISSR, 0x01, 0x20); 4565 4566 /* Save mode number in CR34 */ 4567 outSISIDXREG(SISCR, 0x34, 0x2e); 4568 4569 /* Let everyone know what the current mode is */ 4570 ivideo->modeprechange = 0x2e; 4571} 4572#endif 4573 4574#ifdef CONFIG_FB_SIS_315 4575 4576static void __devinit 4577sisfb_post_xgi_delay(struct sis_video_info *ivideo, int delay) 4578{ 4579 unsigned int i; 4580 u8 reg; 4581 4582 for(i = 0; i <= (delay * 10 * 36); i++) { 4583 inSISIDXREG(SISSR, 0x05, reg); 4584 reg++; 4585 } 4586} 4587 4588static int __devinit 4589sisfb_find_host_bridge(struct sis_video_info *ivideo, struct pci_dev *mypdev, 4590 unsigned short pcivendor) 4591{ 4592 struct pci_dev *pdev = NULL; 4593 unsigned short temp; 4594 int ret = 0; 4595 4596 while((pdev = pci_get_class(PCI_CLASS_BRIDGE_HOST, pdev))) { 4597 temp = pdev->vendor; 4598 pci_dev_put(pdev); 4599 if(temp == pcivendor) { 4600 ret = 1; 4601 break; 4602 } 4603 } 4604 4605 return ret; 4606} 4607 4608static int __devinit 4609sisfb_post_xgi_rwtest(struct sis_video_info *ivideo, int starta, 4610 unsigned int enda, unsigned int mapsize) 4611{ 4612 unsigned int pos; 4613 int i; 4614 4615 writel(0, ivideo->video_vbase); 4616 4617 for(i = starta; i <= enda; i++) { 4618 pos = 1 << i; 4619 if(pos < mapsize) 4620 writel(pos, ivideo->video_vbase + pos); 4621 } 4622 4623 sisfb_post_xgi_delay(ivideo, 150); 4624 4625 if(readl(ivideo->video_vbase) != 0) 4626 return 0; 4627 4628 for(i = starta; i <= enda; i++) { 4629 pos = 1 << i; 4630 if(pos < mapsize) { 4631 if(readl(ivideo->video_vbase + pos) != pos) 4632 return 0; 4633 } else 4634 return 0; 4635 } 4636 4637 return 1; 4638} 4639 4640static void __devinit 4641sisfb_post_xgi_ramsize(struct sis_video_info *ivideo) 4642{ 4643 unsigned int buswidth, ranksize, channelab, mapsize; 4644 int i, j, k, l; 4645 u8 reg, sr14; 4646 static const u8 dramsr13[12 * 5] = { 4647 0x02, 0x0e, 0x0b, 0x80, 0x5d, 4648 0x02, 0x0e, 0x0a, 0x40, 0x59, 4649 0x02, 0x0d, 0x0b, 0x40, 0x4d, 4650 0x02, 0x0e, 0x09, 0x20, 0x55, 4651 0x02, 0x0d, 0x0a, 0x20, 0x49, 4652 0x02, 0x0c, 0x0b, 0x20, 0x3d, 4653 0x02, 0x0e, 0x08, 0x10, 0x51, 4654 0x02, 0x0d, 0x09, 0x10, 0x45, 4655 0x02, 0x0c, 0x0a, 0x10, 0x39, 4656 0x02, 0x0d, 0x08, 0x08, 0x41, 4657 0x02, 0x0c, 0x09, 0x08, 0x35, 4658 0x02, 0x0c, 0x08, 0x04, 0x31 4659 }; 4660 static const u8 dramsr13_4[4 * 5] = { 4661 0x02, 0x0d, 0x09, 0x40, 0x45, 4662 0x02, 0x0c, 0x09, 0x20, 0x35, 4663 0x02, 0x0c, 0x08, 0x10, 0x31, 4664 0x02, 0x0b, 0x08, 0x08, 0x21 4665 }; 4666 4667 /* Enable linear mode, disable 0xa0000 address decoding */ 4668 /* We disable a0000 address decoding, because 4669 * - if running on x86, if the card is disabled, it means 4670 * that another card is in the system. We don't want 4671 * to interphere with that primary card's textmode. 4672 * - if running on non-x86, there usually is no VGA window 4673 * at a0000. 4674 */ 4675 orSISIDXREG(SISSR, 0x20, (0x80 | 0x04)); 4676 4677 /* Need to map max FB size for finding out about RAM size */ 4678 mapsize = 256 << 20; 4679 sisfb_post_map_vram(ivideo, &mapsize, 32); 4680 4681 if(!ivideo->video_vbase) { 4682 printk(KERN_ERR "sisfb: Unable to detect RAM size. Setting default.\n"); 4683 outSISIDXREG(SISSR, 0x13, 0x35); 4684 outSISIDXREG(SISSR, 0x14, 0x41); 4685 /* TODO */ 4686 return; 4687 } 4688 4689 /* Non-interleaving */ 4690 outSISIDXREG(SISSR, 0x15, 0x00); 4691 /* No tiling */ 4692 outSISIDXREG(SISSR, 0x1c, 0x00); 4693 4694 if(ivideo->chip == XGI_20) { 4695 4696 channelab = 1; 4697 inSISIDXREG(SISCR, 0x97, reg); 4698 if(!(reg & 0x01)) { /* Single 32/16 */ 4699 buswidth = 32; 4700 outSISIDXREG(SISSR, 0x13, 0xb1); 4701 outSISIDXREG(SISSR, 0x14, 0x52); 4702 sisfb_post_xgi_delay(ivideo, 1); 4703 sr14 = 0x02; 4704 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) 4705 goto bail_out; 4706 4707 outSISIDXREG(SISSR, 0x13, 0x31); 4708 outSISIDXREG(SISSR, 0x14, 0x42); 4709 sisfb_post_xgi_delay(ivideo, 1); 4710 if(sisfb_post_xgi_rwtest(ivideo, 23, 23, mapsize)) 4711 goto bail_out; 4712 4713 buswidth = 16; 4714 outSISIDXREG(SISSR, 0x13, 0xb1); 4715 outSISIDXREG(SISSR, 0x14, 0x41); 4716 sisfb_post_xgi_delay(ivideo, 1); 4717 sr14 = 0x01; 4718 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize)) 4719 goto bail_out; 4720 else 4721 outSISIDXREG(SISSR, 0x13, 0x31); 4722 } else { /* Dual 16/8 */ 4723 buswidth = 16; 4724 outSISIDXREG(SISSR, 0x13, 0xb1); 4725 outSISIDXREG(SISSR, 0x14, 0x41); 4726 sisfb_post_xgi_delay(ivideo, 1); 4727 sr14 = 0x01; 4728 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize)) 4729 goto bail_out; 4730 4731 outSISIDXREG(SISSR, 0x13, 0x31); 4732 outSISIDXREG(SISSR, 0x14, 0x31); 4733 sisfb_post_xgi_delay(ivideo, 1); 4734 if(sisfb_post_xgi_rwtest(ivideo, 22, 22, mapsize)) 4735 goto bail_out; 4736 4737 buswidth = 8; 4738 outSISIDXREG(SISSR, 0x13, 0xb1); 4739 outSISIDXREG(SISSR, 0x14, 0x30); 4740 sisfb_post_xgi_delay(ivideo, 1); 4741 sr14 = 0x00; 4742 if(sisfb_post_xgi_rwtest(ivideo, 21, 22, mapsize)) 4743 goto bail_out; 4744 else 4745 outSISIDXREG(SISSR, 0x13, 0x31); 4746 } 4747 4748 } else { /* XGI_40 */ 4749 4750 inSISIDXREG(SISCR, 0x97, reg); 4751 if(!(reg & 0x10)) { 4752 inSISIDXREG(SISSR, 0x39, reg); 4753 reg >>= 1; 4754 } 4755 4756 if(reg & 0x01) { /* DDRII */ 4757 buswidth = 32; 4758 if(ivideo->revision_id == 2) { 4759 channelab = 2; 4760 outSISIDXREG(SISSR, 0x13, 0xa1); 4761 outSISIDXREG(SISSR, 0x14, 0x44); 4762 sr14 = 0x04; 4763 sisfb_post_xgi_delay(ivideo, 1); 4764 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) 4765 goto bail_out; 4766 4767 outSISIDXREG(SISSR, 0x13, 0x21); 4768 outSISIDXREG(SISSR, 0x14, 0x34); 4769 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize)) 4770 goto bail_out; 4771 4772 channelab = 1; 4773 outSISIDXREG(SISSR, 0x13, 0xa1); 4774 outSISIDXREG(SISSR, 0x14, 0x40); 4775 sr14 = 0x00; 4776 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize)) 4777 goto bail_out; 4778 4779 outSISIDXREG(SISSR, 0x13, 0x21); 4780 outSISIDXREG(SISSR, 0x14, 0x30); 4781 } else { 4782 channelab = 3; 4783 outSISIDXREG(SISSR, 0x13, 0xa1); 4784 outSISIDXREG(SISSR, 0x14, 0x4c); 4785 sr14 = 0x0c; 4786 sisfb_post_xgi_delay(ivideo, 1); 4787 if(sisfb_post_xgi_rwtest(ivideo, 23, 25, mapsize)) 4788 goto bail_out; 4789 4790 channelab = 2; 4791 outSISIDXREG(SISSR, 0x14, 0x48); 4792 sisfb_post_xgi_delay(ivideo, 1); 4793 sr14 = 0x08; 4794 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) 4795 goto bail_out; 4796 4797 outSISIDXREG(SISSR, 0x13, 0x21); 4798 outSISIDXREG(SISSR, 0x14, 0x3c); 4799 sr14 = 0x0c; 4800 4801 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) { 4802 channelab = 3; 4803 } else { 4804 channelab = 2; 4805 outSISIDXREG(SISSR, 0x14, 0x38); 4806 sr14 = 0x08; 4807 } 4808 } 4809 sisfb_post_xgi_delay(ivideo, 1); 4810 4811 } else { /* DDR */ 4812 4813 buswidth = 64; 4814 if(ivideo->revision_id == 2) { 4815 channelab = 1; 4816 outSISIDXREG(SISSR, 0x13, 0xa1); 4817 outSISIDXREG(SISSR, 0x14, 0x52); 4818 sisfb_post_xgi_delay(ivideo, 1); 4819 sr14 = 0x02; 4820 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) 4821 goto bail_out; 4822 4823 outSISIDXREG(SISSR, 0x13, 0x21); 4824 outSISIDXREG(SISSR, 0x14, 0x42); 4825 } else { 4826 channelab = 2; 4827 outSISIDXREG(SISSR, 0x13, 0xa1); 4828 outSISIDXREG(SISSR, 0x14, 0x5a); 4829 sisfb_post_xgi_delay(ivideo, 1); 4830 sr14 = 0x0a; 4831 if(sisfb_post_xgi_rwtest(ivideo, 24, 25, mapsize)) 4832 goto bail_out; 4833 4834 outSISIDXREG(SISSR, 0x13, 0x21); 4835 outSISIDXREG(SISSR, 0x14, 0x4a); 4836 } 4837 sisfb_post_xgi_delay(ivideo, 1); 4838 4839 } 4840 } 4841 4842bail_out: 4843 setSISIDXREG(SISSR, 0x14, 0xf0, sr14); 4844 sisfb_post_xgi_delay(ivideo, 1); 4845 4846 j = (ivideo->chip == XGI_20) ? 5 : 9; 4847 k = (ivideo->chip == XGI_20) ? 12 : 4; 4848 4849 for(i = 0; i < k; i++) { 4850 4851 reg = (ivideo->chip == XGI_20) ? 4852 dramsr13[(i * 5) + 4] : dramsr13_4[(i * 5) + 4]; 4853 setSISIDXREG(SISSR, 0x13, 0x80, reg); 4854 sisfb_post_xgi_delay(ivideo, 50); 4855 4856 ranksize = (ivideo->chip == XGI_20) ? 4857 dramsr13[(i * 5) + 3] : dramsr13_4[(i * 5) + 3]; 4858 4859 inSISIDXREG(SISSR, 0x13, reg); 4860 if(reg & 0x80) ranksize <<= 1; 4861 4862 if(ivideo->chip == XGI_20) { 4863 if(buswidth == 16) ranksize <<= 1; 4864 else if(buswidth == 32) ranksize <<= 2; 4865 } else { 4866 if(buswidth == 64) ranksize <<= 1; 4867 } 4868 4869 reg = 0; 4870 l = channelab; 4871 if(l == 3) l = 4; 4872 if((ranksize * l) <= 256) { 4873 while((ranksize >>= 1)) reg += 0x10; 4874 } 4875 4876 if(!reg) continue; 4877 4878 setSISIDXREG(SISSR, 0x14, 0x0f, (reg & 0xf0)); 4879 sisfb_post_xgi_delay(ivideo, 1); 4880 4881 if(sisfb_post_xgi_rwtest(ivideo, j, ((reg >> 4) + channelab - 2 + 20), mapsize)) 4882 break; 4883 } 4884 4885 iounmap(ivideo->video_vbase); 4886} 4887 4888static void __devinit 4889sisfb_post_xgi_setclocks(struct sis_video_info *ivideo, u8 regb) 4890{ 4891 u8 v1, v2, v3; 4892 int index; 4893 static const u8 cs90[8 * 3] = { 4894 0x16, 0x01, 0x01, 4895 0x3e, 0x03, 0x01, 4896 0x7c, 0x08, 0x01, 4897 0x79, 0x06, 0x01, 4898 0x29, 0x01, 0x81, 4899 0x5c, 0x23, 0x01, 4900 0x5c, 0x23, 0x01, 4901 0x5c, 0x23, 0x01 4902 }; 4903 static const u8 csb8[8 * 3] = { 4904 0x5c, 0x23, 0x01, 4905 0x29, 0x01, 0x01, 4906 0x7c, 0x08, 0x01, 4907 0x79, 0x06, 0x01, 4908 0x29, 0x01, 0x81, 4909 0x5c, 0x23, 0x01, 4910 0x5c, 0x23, 0x01, 4911 0x5c, 0x23, 0x01 4912 }; 4913 4914 regb = 0; /* ! */ 4915 4916 index = regb * 3; 4917 v1 = cs90[index]; v2 = cs90[index + 1]; v3 = cs90[index + 2]; 4918 if(ivideo->haveXGIROM) { 4919 v1 = ivideo->bios_abase[0x90 + index]; 4920 v2 = ivideo->bios_abase[0x90 + index + 1]; 4921 v3 = ivideo->bios_abase[0x90 + index + 2]; 4922 } 4923 outSISIDXREG(SISSR, 0x28, v1); 4924 outSISIDXREG(SISSR, 0x29, v2); 4925 outSISIDXREG(SISSR, 0x2a, v3); 4926 sisfb_post_xgi_delay(ivideo, 0x43); 4927 sisfb_post_xgi_delay(ivideo, 0x43); 4928 sisfb_post_xgi_delay(ivideo, 0x43); 4929 index = regb * 3; 4930 v1 = csb8[index]; v2 = csb8[index + 1]; v3 = csb8[index + 2]; 4931 if(ivideo->haveXGIROM) { 4932 v1 = ivideo->bios_abase[0xb8 + index]; 4933 v2 = ivideo->bios_abase[0xb8 + index + 1]; 4934 v3 = ivideo->bios_abase[0xb8 + index + 2]; 4935 } 4936 outSISIDXREG(SISSR, 0x2e, v1); 4937 outSISIDXREG(SISSR, 0x2f, v2); 4938 outSISIDXREG(SISSR, 0x30, v3); 4939 sisfb_post_xgi_delay(ivideo, 0x43); 4940 sisfb_post_xgi_delay(ivideo, 0x43); 4941 sisfb_post_xgi_delay(ivideo, 0x43); 4942} 4943 4944static int __devinit 4945sisfb_post_xgi(struct pci_dev *pdev) 4946{ 4947 struct sis_video_info *ivideo = pci_get_drvdata(pdev); 4948 unsigned char *bios = ivideo->bios_abase; 4949 struct pci_dev *mypdev = NULL; 4950 const u8 *ptr, *ptr2; 4951 u8 v1, v2, v3, v4, v5, reg, ramtype; 4952 u32 rega, regb, regd; 4953 int i, j, k, index; 4954 static const u8 cs78[3] = { 0xf6, 0x0d, 0x00 }; 4955 static const u8 cs76[2] = { 0xa3, 0xfb }; 4956 static const u8 cs7b[3] = { 0xc0, 0x11, 0x00 }; 4957 static const u8 cs158[8] = { 4958 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00 4959 }; 4960 static const u8 cs160[8] = { 4961 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00 4962 }; 4963 static const u8 cs168[8] = { 4964 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00 4965 }; 4966 static const u8 cs128[3 * 8] = { 4967 0x90, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 4968 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 4969 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00 4970 }; 4971 static const u8 cs148[2 * 8] = { 4972 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 4973 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 4974 }; 4975 static const u8 cs31a[8 * 4] = { 4976 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 4977 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 4978 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 4979 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 4980 }; 4981 static const u8 cs33a[8 * 4] = { 4982 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 4983 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 4984 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 4985 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 4986 }; 4987 static const u8 cs45a[8 * 2] = { 4988 0x00, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x00, 0x00, 4989 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 4990 }; 4991 static const u8 cs170[7 * 8] = { 4992 0x54, 0x32, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 4993 0x54, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 4994 0x0a, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 4995 0x44, 0x34, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 4996 0x10, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 4997 0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 4998 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00 4999 }; 5000 static const u8 cs1a8[3 * 8] = { 5001 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 5002 0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 5003 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 5004 }; 5005 static const u8 cs100[2 * 8] = { 5006 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 5007 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 5008 }; 5009 5010 /* VGA enable */ 5011 reg = inSISREG(SISVGAENABLE) | 0x01; 5012 outSISREG(SISVGAENABLE, reg); 5013 5014 /* Misc */ 5015 reg = inSISREG(SISMISCR) | 0x01; 5016 outSISREG(SISMISCW, reg); 5017 5018 /* Unlock SR */ 5019 outSISIDXREG(SISSR, 0x05, 0x86); 5020 inSISIDXREG(SISSR, 0x05, reg); 5021 if(reg != 0xa1) 5022 return 0; 5023 5024 /* Clear some regs */ 5025 for(i = 0; i < 0x22; i++) { 5026 if(0x06 + i == 0x20) continue; 5027 outSISIDXREG(SISSR, 0x06 + i, 0x00); 5028 } 5029 for(i = 0; i < 0x0b; i++) { 5030 outSISIDXREG(SISSR, 0x31 + i, 0x00); 5031 } 5032 for(i = 0; i < 0x10; i++) { 5033 outSISIDXREG(SISCR, 0x30 + i, 0x00); 5034 } 5035 5036 ptr = cs78; 5037 if(ivideo->haveXGIROM) { 5038 ptr = (const u8 *)&bios[0x78]; 5039 } 5040 for(i = 0; i < 3; i++) { 5041 outSISIDXREG(SISSR, 0x23 + i, ptr[i]); 5042 } 5043 5044 ptr = cs76; 5045 if(ivideo->haveXGIROM) { 5046 ptr = (const u8 *)&bios[0x76]; 5047 } 5048 for(i = 0; i < 2; i++) { 5049 outSISIDXREG(SISSR, 0x21 + i, ptr[i]); 5050 } 5051 5052 v1 = 0x18; v2 = 0x00; 5053 if(ivideo->haveXGIROM) { 5054 v1 = bios[0x74]; 5055 v2 = bios[0x75]; 5056 } 5057 outSISIDXREG(SISSR, 0x07, v1); 5058 outSISIDXREG(SISSR, 0x11, 0x0f); 5059 outSISIDXREG(SISSR, 0x1f, v2); 5060 /* PCI linear mode, RelIO enabled, A0000 decoding disabled */ 5061 outSISIDXREG(SISSR, 0x20, 0x80 | 0x20 | 0x04); 5062 outSISIDXREG(SISSR, 0x27, 0x74); 5063 5064 ptr = cs7b; 5065 if(ivideo->haveXGIROM) { 5066 ptr = (const u8 *)&bios[0x7b]; 5067 } 5068 for(i = 0; i < 3; i++) { 5069 outSISIDXREG(SISSR, 0x31 + i, ptr[i]); 5070 } 5071 5072 if(ivideo->chip == XGI_40) { 5073 if(ivideo->revision_id == 2) { 5074 setSISIDXREG(SISSR, 0x3b, 0x3f, 0xc0); 5075 } 5076 outSISIDXREG(SISCR, 0x7d, 0xfe); 5077 outSISIDXREG(SISCR, 0x7e, 0x0f); 5078 } 5079 if(ivideo->revision_id == 0) { /* 40 *and* 20? */ 5080 andSISIDXREG(SISCR, 0x58, 0xd7); 5081 inSISIDXREG(SISCR, 0xcb, reg); 5082 if(reg & 0x20) { 5083 setSISIDXREG(SISCR, 0x58, 0xd7, (reg & 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */ 5084 } 5085 } 5086 5087 reg = (ivideo->chip == XGI_40) ? 0x20 : 0x00; 5088 setSISIDXREG(SISCR, 0x38, 0x1f, reg); 5089 5090 if(ivideo->chip == XGI_20) { 5091 outSISIDXREG(SISSR, 0x36, 0x70); 5092 } else { 5093 outSISIDXREG(SISVID, 0x00, 0x86); 5094 outSISIDXREG(SISVID, 0x32, 0x00); 5095 outSISIDXREG(SISVID, 0x30, 0x00); 5096 outSISIDXREG(SISVID, 0x32, 0x01); 5097 outSISIDXREG(SISVID, 0x30, 0x00); 5098 andSISIDXREG(SISVID, 0x2f, 0xdf); 5099 andSISIDXREG(SISCAP, 0x00, 0x3f); 5100 5101 outSISIDXREG(SISPART1, 0x2f, 0x01); 5102 outSISIDXREG(SISPART1, 0x00, 0x00); 5103 outSISIDXREG(SISPART1, 0x02, bios[0x7e]); 5104 outSISIDXREG(SISPART1, 0x2e, 0x08); 5105 andSISIDXREG(SISPART1, 0x35, 0x7f); 5106 andSISIDXREG(SISPART1, 0x50, 0xfe); 5107 5108 inSISIDXREG(SISPART4, 0x00, reg); 5109 if(reg == 1 || reg == 2) { 5110 outSISIDXREG(SISPART2, 0x00, 0x1c); 5111 outSISIDXREG(SISPART4, 0x0d, bios[0x7f]); 5112 outSISIDXREG(SISPART4, 0x0e, bios[0x80]); 5113 outSISIDXREG(SISPART4, 0x10, bios[0x81]); 5114 andSISIDXREG(SISPART4, 0x0f, 0x3f); 5115 5116 inSISIDXREG(SISPART4, 0x01, reg); 5117 if((reg & 0xf0) >= 0xb0) { 5118 inSISIDXREG(SISPART4, 0x23, reg); 5119 if(reg & 0x20) reg |= 0x40; 5120 outSISIDXREG(SISPART4, 0x23, reg); 5121 reg = (reg & 0x20) ? 0x02 : 0x00; 5122 setSISIDXREG(SISPART1, 0x1e, 0xfd, reg); 5123 } 5124 } 5125 5126 v1 = bios[0x77]; 5127 5128 inSISIDXREG(SISSR, 0x3b, reg); 5129 if(reg & 0x02) { 5130 inSISIDXREG(SISSR, 0x3a, reg); 5131 v2 = (reg & 0x30) >> 3; 5132 if(!(v2 & 0x04)) v2 ^= 0x02; 5133 inSISIDXREG(SISSR, 0x39, reg); 5134 if(reg & 0x80) v2 |= 0x80; 5135 v2 |= 0x01; 5136 5137 if((mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0730, NULL))) { 5138 pci_dev_put(mypdev); 5139 if(((v2 & 0x06) == 2) || ((v2 & 0x06) == 4)) 5140 v2 &= 0xf9; 5141 v2 |= 0x08; 5142 v1 &= 0xfe; 5143 } else { 5144 mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0735, NULL); 5145 if(!mypdev) 5146 mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0645, NULL); 5147 if(!mypdev) 5148 mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0650, NULL); 5149 if(mypdev) { 5150 pci_read_config_dword(mypdev, 0x94, ®d); 5151 regd &= 0xfffffeff; 5152 pci_write_config_dword(mypdev, 0x94, regd); 5153 v1 &= 0xfe; 5154 pci_dev_put(mypdev); 5155 } else if(sisfb_find_host_bridge(ivideo, pdev, PCI_VENDOR_ID_SI)) { 5156 v1 &= 0xfe; 5157 } else if(sisfb_find_host_bridge(ivideo, pdev, 0x1106) || 5158 sisfb_find_host_bridge(ivideo, pdev, 0x1022) || 5159 sisfb_find_host_bridge(ivideo, pdev, 0x700e) || 5160 sisfb_find_host_bridge(ivideo, pdev, 0x10de)) { 5161 if((v2 & 0x06) == 4) 5162 v2 ^= 0x06; 5163 v2 |= 0x08; 5164 } 5165 } 5166 setSISIDXREG(SISCR, 0x5f, 0xf0, v2); 5167 } 5168 outSISIDXREG(SISSR, 0x22, v1); 5169 5170 if(ivideo->revision_id == 2) { 5171 inSISIDXREG(SISSR, 0x3b, v1); 5172 inSISIDXREG(SISSR, 0x3a, v2); 5173 regd = bios[0x90 + 3] | (bios[0x90 + 4] << 8); 5174 if( (!(v1 & 0x02)) && (v2 & 0x30) && (regd < 0xcf) ) 5175 setSISIDXREG(SISCR, 0x5f, 0xf1, 0x01); 5176 5177 if((mypdev = pci_get_device(0x10de, 0x01e0, NULL))) { 5178 /* TODO: set CR5f &0xf1 | 0x01 for version 6570 5179 * of nforce 2 ROM 5180 */ 5181 if(0) 5182 setSISIDXREG(SISCR, 0x5f, 0xf1, 0x01); 5183 pci_dev_put(mypdev); 5184 } 5185 } 5186 5187 v1 = 0x30; 5188 inSISIDXREG(SISSR, 0x3b, reg); 5189 inSISIDXREG(SISCR, 0x5f, v2); 5190 if((!(reg & 0x02)) && (v2 & 0x0e)) 5191 v1 |= 0x08; 5192 outSISIDXREG(SISSR, 0x27, v1); 5193 5194 if(bios[0x64] & 0x01) { 5195 setSISIDXREG(SISCR, 0x5f, 0xf0, bios[0x64]); 5196 } 5197 5198 v1 = bios[0x4f7]; 5199 pci_read_config_dword(pdev, 0x50, ®d); 5200 regd = (regd >> 20) & 0x0f; 5201 if(regd == 1) { 5202 v1 &= 0xfc; 5203 orSISIDXREG(SISCR, 0x5f, 0x08); 5204 } 5205 outSISIDXREG(SISCR, 0x48, v1); 5206 5207 setSISIDXREG(SISCR, 0x47, 0x04, bios[0x4f6] & 0xfb); 5208 setSISIDXREG(SISCR, 0x49, 0xf0, bios[0x4f8] & 0x0f); 5209 setSISIDXREG(SISCR, 0x4a, 0x60, bios[0x4f9] & 0x9f); 5210 setSISIDXREG(SISCR, 0x4b, 0x08, bios[0x4fa] & 0xf7); 5211 setSISIDXREG(SISCR, 0x4c, 0x80, bios[0x4fb] & 0x7f); 5212 outSISIDXREG(SISCR, 0x70, bios[0x4fc]); 5213 setSISIDXREG(SISCR, 0x71, 0xf0, bios[0x4fd] & 0x0f); 5214 outSISIDXREG(SISCR, 0x74, 0xd0); 5215 setSISIDXREG(SISCR, 0x74, 0xcf, bios[0x4fe] & 0x30); 5216 setSISIDXREG(SISCR, 0x75, 0xe0, bios[0x4ff] & 0x1f); 5217 setSISIDXREG(SISCR, 0x76, 0xe0, bios[0x500] & 0x1f); 5218 v1 = bios[0x501]; 5219 if((mypdev = pci_get_device(0x8086, 0x2530, NULL))) { 5220 v1 = 0xf0; 5221 pci_dev_put(mypdev); 5222 } 5223 outSISIDXREG(SISCR, 0x77, v1); 5224 } 5225 5226 /* RAM type */ 5227 5228 regb = 0; /* ! */ 5229 5230 v1 = 0xff; 5231 if(ivideo->haveXGIROM) { 5232 v1 = bios[0x140 + regb]; 5233 } 5234 outSISIDXREG(SISCR, 0x6d, v1); 5235 5236 ptr = cs128; 5237 if(ivideo->haveXGIROM) { 5238 ptr = (const u8 *)&bios[0x128]; 5239 } 5240 for(i = 0, j = 0; i < 3; i++, j += 8) { 5241 outSISIDXREG(SISCR, 0x68 + i, ptr[j + regb]); 5242 } 5243 5244 ptr = cs31a; 5245 ptr2 = cs33a; 5246 if(ivideo->haveXGIROM) { 5247 index = (ivideo->chip == XGI_20) ? 0x31a : 0x3a6; 5248 ptr = (const u8 *)&bios[index]; 5249 ptr2 = (const u8 *)&bios[index + 0x20]; 5250 } 5251 for(i = 0; i < 2; i++) { 5252 if(i == 0) { 5253 regd = le32_to_cpu(((u32 *)ptr)[regb]); 5254 rega = 0x6b; 5255 } else { 5256 regd = le32_to_cpu(((u32 *)ptr2)[regb]); 5257 rega = 0x6e; 5258 } 5259 reg = 0x00; 5260 for(j = 0; j < 16; j++) { 5261 reg &= 0xf3; 5262 if(regd & 0x01) reg |= 0x04; 5263 if(regd & 0x02) reg |= 0x08; 5264 regd >>= 2; 5265 outSISIDXREG(SISCR, rega, reg); 5266 inSISIDXREG(SISCR, rega, reg); 5267 inSISIDXREG(SISCR, rega, reg); 5268 reg += 0x10; 5269 } 5270 } 5271 5272 andSISIDXREG(SISCR, 0x6e, 0xfc); 5273 5274 ptr = NULL; 5275 if(ivideo->haveXGIROM) { 5276 index = (ivideo->chip == XGI_20) ? 0x35a : 0x3e6; 5277 ptr = (const u8 *)&bios[index]; 5278 } 5279 for(i = 0; i < 4; i++) { 5280 setSISIDXREG(SISCR, 0x6e, 0xfc, i); 5281 reg = 0x00; 5282 for(j = 0; j < 2; j++) { 5283 regd = 0; 5284 if(ptr) { 5285 regd = le32_to_cpu(((u32 *)ptr)[regb * 8]); 5286 ptr += 4; 5287 } 5288 /* reg = 0x00; */ 5289 for(k = 0; k < 16; k++) { 5290 reg &= 0xfc; 5291 if(regd & 0x01) reg |= 0x01; 5292 if(regd & 0x02) reg |= 0x02; 5293 regd >>= 2; 5294 outSISIDXREG(SISCR, 0x6f, reg); 5295 inSISIDXREG(SISCR, 0x6f, reg); 5296 inSISIDXREG(SISCR, 0x6f, reg); 5297 reg += 0x08; 5298 } 5299 } 5300 } 5301 5302 ptr = cs148; 5303 if(ivideo->haveXGIROM) { 5304 ptr = (const u8 *)&bios[0x148]; 5305 } 5306 for(i = 0, j = 0; i < 2; i++, j += 8) { 5307 outSISIDXREG(SISCR, 0x80 + i, ptr[j + regb]); 5308 } 5309 5310 andSISIDXREG(SISCR, 0x89, 0x8f); 5311 5312 ptr = cs45a; 5313 if(ivideo->haveXGIROM) { 5314 index = (ivideo->chip == XGI_20) ? 0x45a : 0x4e6; 5315 ptr = (const u8 *)&bios[index]; 5316 } 5317 regd = le16_to_cpu(((const u16 *)ptr)[regb]); 5318 reg = 0x80; 5319 for(i = 0; i < 5; i++) { 5320 reg &= 0xfc; 5321 if(regd & 0x01) reg |= 0x01; 5322 if(regd & 0x02) reg |= 0x02; 5323 regd >>= 2; 5324 outSISIDXREG(SISCR, 0x89, reg); 5325 inSISIDXREG(SISCR, 0x89, reg); 5326 inSISIDXREG(SISCR, 0x89, reg); 5327 reg += 0x10; 5328 } 5329 5330 v1 = 0xb5; v2 = 0x20; v3 = 0xf0; v4 = 0x13; 5331 if(ivideo->haveXGIROM) { 5332 v1 = bios[0x118 + regb]; 5333 v2 = bios[0xf8 + regb]; 5334 v3 = bios[0x120 + regb]; 5335 v4 = bios[0x1ca]; 5336 } 5337 outSISIDXREG(SISCR, 0x45, v1 & 0x0f); 5338 outSISIDXREG(SISCR, 0x99, (v1 >> 4) & 0x07); 5339 orSISIDXREG(SISCR, 0x40, v1 & 0x80); 5340 outSISIDXREG(SISCR, 0x41, v2); 5341 5342 ptr = cs170; 5343 if(ivideo->haveXGIROM) { 5344 ptr = (const u8 *)&bios[0x170]; 5345 } 5346 for(i = 0, j = 0; i < 7; i++, j += 8) { 5347 outSISIDXREG(SISCR, 0x90 + i, ptr[j + regb]); 5348 } 5349 5350 outSISIDXREG(SISCR, 0x59, v3); 5351 5352 ptr = cs1a8; 5353 if(ivideo->haveXGIROM) { 5354 ptr = (const u8 *)&bios[0x1a8]; 5355 } 5356 for(i = 0, j = 0; i < 3; i++, j += 8) { 5357 outSISIDXREG(SISCR, 0xc3 + i, ptr[j + regb]); 5358 } 5359 5360 ptr = cs100; 5361 if(ivideo->haveXGIROM) { 5362 ptr = (const u8 *)&bios[0x100]; 5363 } 5364 for(i = 0, j = 0; i < 2; i++, j += 8) { 5365 outSISIDXREG(SISCR, 0x8a + i, ptr[j + regb]); 5366 } 5367 5368 outSISIDXREG(SISCR, 0xcf, v4); 5369 5370 outSISIDXREG(SISCR, 0x83, 0x09); 5371 outSISIDXREG(SISCR, 0x87, 0x00); 5372 5373 if(ivideo->chip == XGI_40) { 5374 if( (ivideo->revision_id == 1) || 5375 (ivideo->revision_id == 2) ) { 5376 outSISIDXREG(SISCR, 0x8c, 0x87); 5377 } 5378 } 5379 5380 outSISIDXREG(SISSR, 0x17, 0x00); 5381 outSISIDXREG(SISSR, 0x1a, 0x87); 5382 5383 if(ivideo->chip == XGI_20) { 5384 outSISIDXREG(SISSR, 0x15, 0x00); 5385 outSISIDXREG(SISSR, 0x1c, 0x00); 5386 } 5387 5388 ramtype = 0x00; v1 = 0x10; 5389 if(ivideo->haveXGIROM) { 5390 ramtype = bios[0x62]; 5391 v1 = bios[0x1d2]; 5392 } 5393 if(!(ramtype & 0x80)) { 5394 if(ivideo->chip == XGI_20) { 5395 outSISIDXREG(SISCR, 0x97, v1); 5396 inSISIDXREG(SISCR, 0x97, reg); 5397 if(reg & 0x10) { 5398 ramtype = (reg & 0x01) << 1; 5399 } 5400 } else { 5401 inSISIDXREG(SISSR, 0x39, reg); 5402 ramtype = reg & 0x02; 5403 if(!(ramtype)) { 5404 inSISIDXREG(SISSR, 0x3a, reg); 5405 ramtype = (reg >> 1) & 0x01; 5406 } 5407 } 5408 } 5409 ramtype &= 0x07; 5410 5411 regb = 0; /* ! */ 5412 5413 switch(ramtype) { 5414 case 0: 5415 sisfb_post_xgi_setclocks(ivideo, regb); 5416 if((ivideo->chip == XGI_20) || 5417 (ivideo->revision_id == 1) || 5418 (ivideo->revision_id == 2)) { 5419 v1 = cs158[regb]; v2 = cs160[regb]; v3 = cs168[regb]; 5420 if(ivideo->haveXGIROM) { 5421 v1 = bios[regb + 0x158]; 5422 v2 = bios[regb + 0x160]; 5423 v3 = bios[regb + 0x168]; 5424 } 5425 outSISIDXREG(SISCR, 0x82, v1); 5426 outSISIDXREG(SISCR, 0x85, v2); 5427 outSISIDXREG(SISCR, 0x86, v3); 5428 } else { 5429 outSISIDXREG(SISCR, 0x82, 0x88); 5430 outSISIDXREG(SISCR, 0x86, 0x00); 5431 inSISIDXREG(SISCR, 0x86, reg); 5432 outSISIDXREG(SISCR, 0x86, 0x88); 5433 inSISIDXREG(SISCR, 0x86, reg); 5434 outSISIDXREG(SISCR, 0x86, bios[regb + 0x168]); 5435 outSISIDXREG(SISCR, 0x82, 0x77); 5436 outSISIDXREG(SISCR, 0x85, 0x00); 5437 inSISIDXREG(SISCR, 0x85, reg); 5438 outSISIDXREG(SISCR, 0x85, 0x88); 5439 inSISIDXREG(SISCR, 0x85, reg); 5440 outSISIDXREG(SISCR, 0x85, bios[regb + 0x160]); 5441 outSISIDXREG(SISCR, 0x82, bios[regb + 0x158]); 5442 } 5443 if(ivideo->chip == XGI_40) { 5444 outSISIDXREG(SISCR, 0x97, 0x00); 5445 } 5446 outSISIDXREG(SISCR, 0x98, 0x01); 5447 outSISIDXREG(SISCR, 0x9a, 0x02); 5448 5449 outSISIDXREG(SISSR, 0x18, 0x01); 5450 if((ivideo->chip == XGI_20) || 5451 (ivideo->revision_id == 2)) { 5452 outSISIDXREG(SISSR, 0x19, 0x40); 5453 } else { 5454 outSISIDXREG(SISSR, 0x19, 0x20); 5455 } 5456 outSISIDXREG(SISSR, 0x16, 0x00); 5457 outSISIDXREG(SISSR, 0x16, 0x80); 5458 if((ivideo->chip == XGI_20) || (bios[0x1cb] != 0x0c)) { 5459 sisfb_post_xgi_delay(ivideo, 0x43); 5460 sisfb_post_xgi_delay(ivideo, 0x43); 5461 sisfb_post_xgi_delay(ivideo, 0x43); 5462 outSISIDXREG(SISSR, 0x18, 0x00); 5463 if((ivideo->chip == XGI_20) || 5464 (ivideo->revision_id == 2)) { 5465 outSISIDXREG(SISSR, 0x19, 0x40); 5466 } else { 5467 outSISIDXREG(SISSR, 0x19, 0x20); 5468 } 5469 } else if((ivideo->chip == XGI_40) && (bios[0x1cb] == 0x0c)) { 5470 /* outSISIDXREG(SISSR, 0x16, 0x0c); */ /* ? */ 5471 } 5472 outSISIDXREG(SISSR, 0x16, 0x00); 5473 outSISIDXREG(SISSR, 0x16, 0x80); 5474 sisfb_post_xgi_delay(ivideo, 4); 5475 v1 = 0x31; v2 = 0x03; v3 = 0x83; v4 = 0x03; v5 = 0x83; 5476 if(ivideo->haveXGIROM) { 5477 v1 = bios[0xf0]; 5478 index = (ivideo->chip == XGI_20) ? 0x4b2 : 0x53e; 5479 v2 = bios[index]; 5480 v3 = bios[index + 1]; 5481 v4 = bios[index + 2]; 5482 v5 = bios[index + 3]; 5483 } 5484 outSISIDXREG(SISSR, 0x18, v1); 5485 outSISIDXREG(SISSR, 0x19, ((ivideo->chip == XGI_20) ? 0x02 : 0x01)); 5486 outSISIDXREG(SISSR, 0x16, v2); 5487 outSISIDXREG(SISSR, 0x16, v3); 5488 sisfb_post_xgi_delay(ivideo, 0x43); 5489 outSISIDXREG(SISSR, 0x1b, 0x03); 5490 sisfb_post_xgi_delay(ivideo, 0x22); 5491 outSISIDXREG(SISSR, 0x18, v1); 5492 outSISIDXREG(SISSR, 0x19, 0x00); 5493 outSISIDXREG(SISSR, 0x16, v4); 5494 outSISIDXREG(SISSR, 0x16, v5); 5495 outSISIDXREG(SISSR, 0x1b, 0x00); 5496 break; 5497 case 1: 5498 outSISIDXREG(SISCR, 0x82, 0x77); 5499 outSISIDXREG(SISCR, 0x86, 0x00); 5500 inSISIDXREG(SISCR, 0x86, reg); 5501 outSISIDXREG(SISCR, 0x86, 0x88); 5502 inSISIDXREG(SISCR, 0x86, reg); 5503 v1 = cs168[regb]; v2 = cs160[regb]; v3 = cs158[regb]; 5504 if(ivideo->haveXGIROM) { 5505 v1 = bios[regb + 0x168]; 5506 v2 = bios[regb + 0x160]; 5507 v3 = bios[regb + 0x158]; 5508 } 5509 outSISIDXREG(SISCR, 0x86, v1); 5510 outSISIDXREG(SISCR, 0x82, 0x77); 5511 outSISIDXREG(SISCR, 0x85, 0x00); 5512 inSISIDXREG(SISCR, 0x85, reg); 5513 outSISIDXREG(SISCR, 0x85, 0x88); 5514 inSISIDXREG(SISCR, 0x85, reg); 5515 outSISIDXREG(SISCR, 0x85, v2); 5516 outSISIDXREG(SISCR, 0x82, v3); 5517 outSISIDXREG(SISCR, 0x98, 0x01); 5518 outSISIDXREG(SISCR, 0x9a, 0x02); 5519 5520 outSISIDXREG(SISSR, 0x28, 0x64); 5521 outSISIDXREG(SISSR, 0x29, 0x63); 5522 sisfb_post_xgi_delay(ivideo, 15); 5523 outSISIDXREG(SISSR, 0x18, 0x00); 5524 outSISIDXREG(SISSR, 0x19, 0x20); 5525 outSISIDXREG(SISSR, 0x16, 0x00); 5526 outSISIDXREG(SISSR, 0x16, 0x80); 5527 outSISIDXREG(SISSR, 0x18, 0xc5); 5528 outSISIDXREG(SISSR, 0x19, 0x23); 5529 outSISIDXREG(SISSR, 0x16, 0x00); 5530 outSISIDXREG(SISSR, 0x16, 0x80); 5531 sisfb_post_xgi_delay(ivideo, 1); 5532 outSISIDXREG(SISCR, 0x97,0x11); 5533 sisfb_post_xgi_setclocks(ivideo, regb); 5534 sisfb_post_xgi_delay(ivideo, 0x46); 5535 outSISIDXREG(SISSR, 0x18, 0xc5); 5536 outSISIDXREG(SISSR, 0x19, 0x23); 5537 outSISIDXREG(SISSR, 0x16, 0x00); 5538 outSISIDXREG(SISSR, 0x16, 0x80); 5539 sisfb_post_xgi_delay(ivideo, 1); 5540 outSISIDXREG(SISSR, 0x1b, 0x04); 5541 sisfb_post_xgi_delay(ivideo, 1); 5542 outSISIDXREG(SISSR, 0x1b, 0x00); 5543 sisfb_post_xgi_delay(ivideo, 1); 5544 v1 = 0x31; 5545 if(ivideo->haveXGIROM) { 5546 v1 = bios[0xf0]; 5547 } 5548 outSISIDXREG(SISSR, 0x18, v1); 5549 outSISIDXREG(SISSR, 0x19, 0x06); 5550 outSISIDXREG(SISSR, 0x16, 0x04); 5551 outSISIDXREG(SISSR, 0x16, 0x84); 5552 sisfb_post_xgi_delay(ivideo, 1); 5553 break; 5554 default: 5555 sisfb_post_xgi_setclocks(ivideo, regb); 5556 if((ivideo->chip == XGI_40) && 5557 ((ivideo->revision_id == 1) || 5558 (ivideo->revision_id == 2))) { 5559 outSISIDXREG(SISCR, 0x82, bios[regb + 0x158]); 5560 outSISIDXREG(SISCR, 0x85, bios[regb + 0x160]); 5561 outSISIDXREG(SISCR, 0x86, bios[regb + 0x168]); 5562 } else { 5563 outSISIDXREG(SISCR, 0x82, 0x88); 5564 outSISIDXREG(SISCR, 0x86, 0x00); 5565 inSISIDXREG(SISCR, 0x86, reg); 5566 outSISIDXREG(SISCR, 0x86, 0x88); 5567 outSISIDXREG(SISCR, 0x82, 0x77); 5568 outSISIDXREG(SISCR, 0x85, 0x00); 5569 inSISIDXREG(SISCR, 0x85, reg); 5570 outSISIDXREG(SISCR, 0x85, 0x88); 5571 inSISIDXREG(SISCR, 0x85, reg); 5572 v1 = cs160[regb]; v2 = cs158[regb]; 5573 if(ivideo->haveXGIROM) { 5574 v1 = bios[regb + 0x160]; 5575 v2 = bios[regb + 0x158]; 5576 } 5577 outSISIDXREG(SISCR, 0x85, v1); 5578 outSISIDXREG(SISCR, 0x82, v2); 5579 } 5580 if(ivideo->chip == XGI_40) { 5581 outSISIDXREG(SISCR, 0x97, 0x11); 5582 } 5583 if((ivideo->chip == XGI_40) && (ivideo->revision_id == 2)) { 5584 outSISIDXREG(SISCR, 0x98, 0x01); 5585 } else { 5586 outSISIDXREG(SISCR, 0x98, 0x03); 5587 } 5588 outSISIDXREG(SISCR, 0x9a, 0x02); 5589 5590 if(ivideo->chip == XGI_40) { 5591 outSISIDXREG(SISSR, 0x18, 0x01); 5592 } else { 5593 outSISIDXREG(SISSR, 0x18, 0x00); 5594 } 5595 outSISIDXREG(SISSR, 0x19, 0x40); 5596 outSISIDXREG(SISSR, 0x16, 0x00); 5597 outSISIDXREG(SISSR, 0x16, 0x80); 5598 if((ivideo->chip == XGI_40) && (bios[0x1cb] != 0x0c)) { 5599 sisfb_post_xgi_delay(ivideo, 0x43); 5600 sisfb_post_xgi_delay(ivideo, 0x43); 5601 sisfb_post_xgi_delay(ivideo, 0x43); 5602 outSISIDXREG(SISSR, 0x18, 0x00); 5603 outSISIDXREG(SISSR, 0x19, 0x40); 5604 outSISIDXREG(SISSR, 0x16, 0x00); 5605 outSISIDXREG(SISSR, 0x16, 0x80); 5606 } 5607 sisfb_post_xgi_delay(ivideo, 4); 5608 v1 = 0x31; 5609 if(ivideo->haveXGIROM) { 5610 v1 = bios[0xf0]; 5611 } 5612 outSISIDXREG(SISSR, 0x18, v1); 5613 outSISIDXREG(SISSR, 0x19, 0x01); 5614 if(ivideo->chip == XGI_40) { 5615 outSISIDXREG(SISSR, 0x16, bios[0x53e]); 5616 outSISIDXREG(SISSR, 0x16, bios[0x53f]); 5617 } else { 5618 outSISIDXREG(SISSR, 0x16, 0x05); 5619 outSISIDXREG(SISSR, 0x16, 0x85); 5620 } 5621 sisfb_post_xgi_delay(ivideo, 0x43); 5622 if(ivideo->chip == XGI_40) { 5623 outSISIDXREG(SISSR, 0x1b, 0x01); 5624 } else { 5625 outSISIDXREG(SISSR, 0x1b, 0x03); 5626 } 5627 sisfb_post_xgi_delay(ivideo, 0x22); 5628 outSISIDXREG(SISSR, 0x18, v1); 5629 outSISIDXREG(SISSR, 0x19, 0x00); 5630 if(ivideo->chip == XGI_40) { 5631 outSISIDXREG(SISSR, 0x16, bios[0x540]); 5632 outSISIDXREG(SISSR, 0x16, bios[0x541]); 5633 } else { 5634 outSISIDXREG(SISSR, 0x16, 0x05); 5635 outSISIDXREG(SISSR, 0x16, 0x85); 5636 } 5637 outSISIDXREG(SISSR, 0x1b, 0x00); 5638 } 5639 5640 regb = 0; /* ! */ 5641 v1 = 0x03; 5642 if(ivideo->haveXGIROM) { 5643 v1 = bios[0x110 + regb]; 5644 } 5645 outSISIDXREG(SISSR, 0x1b, v1); 5646 5647 /* RAM size */ 5648 v1 = 0x00; v2 = 0x00; 5649 if(ivideo->haveXGIROM) { 5650 v1 = bios[0x62]; 5651 v2 = bios[0x63]; 5652 } 5653 regb = 0; /* ! */ 5654 regd = 1 << regb; 5655 if((v1 & 0x40) && (v2 & regd) && ivideo->haveXGIROM) { 5656 5657 outSISIDXREG(SISSR, 0x13, bios[regb + 0xe0]); 5658 outSISIDXREG(SISSR, 0x14, bios[regb + 0xe0 + 8]); 5659 5660 } else { 5661 5662 /* Set default mode, don't clear screen */ 5663 ivideo->SiS_Pr.SiS_UseOEM = false; 5664 SiS_SetEnableDstn(&ivideo->SiS_Pr, false); 5665 SiS_SetEnableFstn(&ivideo->SiS_Pr, false); 5666 ivideo->curFSTN = ivideo->curDSTN = 0; 5667 ivideo->SiS_Pr.VideoMemorySize = 8 << 20; 5668 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80); 5669 5670 outSISIDXREG(SISSR, 0x05, 0x86); 5671 5672 /* Disable read-cache */ 5673 andSISIDXREG(SISSR, 0x21, 0xdf); 5674 sisfb_post_xgi_ramsize(ivideo); 5675 /* Enable read-cache */ 5676 orSISIDXREG(SISSR, 0x21, 0x20); 5677 5678 } 5679 5680 5681 /* Sense CRT1 */ 5682 if(ivideo->chip == XGI_20) { 5683 orSISIDXREG(SISCR, 0x32, 0x20); 5684 } else { 5685 inSISIDXREG(SISPART4, 0x00, reg); 5686 if((reg == 1) || (reg == 2)) { 5687 sisfb_sense_crt1(ivideo); 5688 } else { 5689 orSISIDXREG(SISCR, 0x32, 0x20); 5690 } 5691 } 5692 5693 /* Set default mode, don't clear screen */ 5694 ivideo->SiS_Pr.SiS_UseOEM = false; 5695 SiS_SetEnableDstn(&ivideo->SiS_Pr, false); 5696 SiS_SetEnableFstn(&ivideo->SiS_Pr, false); 5697 ivideo->curFSTN = ivideo->curDSTN = 0; 5698 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80); 5699 5700 outSISIDXREG(SISSR, 0x05, 0x86); 5701 5702 /* Display off */ 5703 orSISIDXREG(SISSR, 0x01, 0x20); 5704 5705 /* Save mode number in CR34 */ 5706 outSISIDXREG(SISCR, 0x34, 0x2e); 5707 5708 /* Let everyone know what the current mode is */ 5709 ivideo->modeprechange = 0x2e; 5710 5711 if(ivideo->chip == XGI_40) { 5712 inSISIDXREG(SISCR, 0xca, reg); 5713 inSISIDXREG(SISCR, 0xcc, v1); 5714 if((reg & 0x10) && (!(v1 & 0x04))) { 5715 printk(KERN_ERR 5716 "sisfb: Please connect power to the card.\n"); 5717 return 0; 5718 } 5719 } 5720 5721 return 1; 5722} 5723#endif 5724 5725static int __devinit 5726sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 5727{ 5728 struct sisfb_chip_info *chipinfo = &sisfb_chip_info[ent->driver_data]; 5729 struct sis_video_info *ivideo = NULL; 5730 struct fb_info *sis_fb_info = NULL; 5731 u16 reg16; 5732 u8 reg; 5733 int i, ret; 5734 5735 if(sisfb_off) 5736 return -ENXIO; 5737 5738 sis_fb_info = framebuffer_alloc(sizeof(*ivideo), &pdev->dev); 5739 if(!sis_fb_info) 5740 return -ENOMEM; 5741 5742 ivideo = (struct sis_video_info *)sis_fb_info->par; 5743 ivideo->memyselfandi = sis_fb_info; 5744 5745 ivideo->sisfb_id = SISFB_ID; 5746 5747 if(card_list == NULL) { 5748 ivideo->cardnumber = 0; 5749 } else { 5750 struct sis_video_info *countvideo = card_list; 5751 ivideo->cardnumber = 1; 5752 while((countvideo = countvideo->next) != 0) 5753 ivideo->cardnumber++; 5754 } 5755 5756 strncpy(ivideo->myid, chipinfo->chip_name, 30); 5757 5758 ivideo->warncount = 0; 5759 ivideo->chip_id = pdev->device; 5760 ivideo->chip_vendor = pdev->vendor; 5761 pci_read_config_byte(pdev, PCI_REVISION_ID, &ivideo->revision_id); 5762 ivideo->SiS_Pr.ChipRevision = ivideo->revision_id; 5763 pci_read_config_word(pdev, PCI_COMMAND, ®16); 5764 ivideo->sisvga_enabled = reg16 & 0x01; 5765 ivideo->pcibus = pdev->bus->number; 5766 ivideo->pcislot = PCI_SLOT(pdev->devfn); 5767 ivideo->pcifunc = PCI_FUNC(pdev->devfn); 5768 ivideo->subsysvendor = pdev->subsystem_vendor; 5769 ivideo->subsysdevice = pdev->subsystem_device; 5770#ifdef SIS_OLD_CONFIG_COMPAT 5771 ivideo->ioctl32registered = 0; 5772#endif 5773 5774#ifndef MODULE 5775 if(sisfb_mode_idx == -1) { 5776 sisfb_get_vga_mode_from_kernel(); 5777 } 5778#endif 5779 5780 ivideo->chip = chipinfo->chip; 5781 ivideo->sisvga_engine = chipinfo->vgaengine; 5782 ivideo->hwcursor_size = chipinfo->hwcursor_size; 5783 ivideo->CRT2_write_enable = chipinfo->CRT2_write_enable; 5784 ivideo->mni = chipinfo->mni; 5785 5786 ivideo->detectedpdc = 0xff; 5787 ivideo->detectedpdca = 0xff; 5788 ivideo->detectedlcda = 0xff; 5789 5790 ivideo->sisfb_thismonitor.datavalid = false; 5791 5792 ivideo->current_base = 0; 5793 5794 ivideo->engineok = 0; 5795 5796 ivideo->sisfb_was_boot_device = 0; 5797#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)) 5798 if(pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW) { 5799 if(ivideo->sisvga_enabled) 5800 ivideo->sisfb_was_boot_device = 1; 5801 else { 5802 printk(KERN_DEBUG "sisfb: PCI device is disabled, " 5803 "but marked as boot video device ???\n"); 5804 printk(KERN_DEBUG "sisfb: I will not accept this " 5805 "as the primary VGA device\n"); 5806 } 5807 } 5808#endif 5809 5810 ivideo->sisfb_parm_mem = sisfb_parm_mem; 5811 ivideo->sisfb_accel = sisfb_accel; 5812 ivideo->sisfb_ypan = sisfb_ypan; 5813 ivideo->sisfb_max = sisfb_max; 5814 ivideo->sisfb_userom = sisfb_userom; 5815 ivideo->sisfb_useoem = sisfb_useoem; 5816 ivideo->sisfb_mode_idx = sisfb_mode_idx; 5817 ivideo->sisfb_parm_rate = sisfb_parm_rate; 5818 ivideo->sisfb_crt1off = sisfb_crt1off; 5819 ivideo->sisfb_forcecrt1 = sisfb_forcecrt1; 5820 ivideo->sisfb_crt2type = sisfb_crt2type; 5821 ivideo->sisfb_crt2flags = sisfb_crt2flags; 5822 /* pdc(a), scalelcd, special timing, lvdshl handled below */ 5823 ivideo->sisfb_dstn = sisfb_dstn; 5824 ivideo->sisfb_fstn = sisfb_fstn; 5825 ivideo->sisfb_tvplug = sisfb_tvplug; 5826 ivideo->sisfb_tvstd = sisfb_tvstd; 5827 ivideo->tvxpos = sisfb_tvxposoffset; 5828 ivideo->tvypos = sisfb_tvyposoffset; 5829 ivideo->sisfb_nocrt2rate = sisfb_nocrt2rate; 5830 ivideo->refresh_rate = 0; 5831 if(ivideo->sisfb_parm_rate != -1) { 5832 ivideo->refresh_rate = ivideo->sisfb_parm_rate; 5833 } 5834 5835 ivideo->SiS_Pr.UsePanelScaler = sisfb_scalelcd; 5836 ivideo->SiS_Pr.CenterScreen = -1; 5837 ivideo->SiS_Pr.SiS_CustomT = sisfb_specialtiming; 5838 ivideo->SiS_Pr.LVDSHL = sisfb_lvdshl; 5839 5840 ivideo->SiS_Pr.SiS_Backup70xx = 0xff; 5841 ivideo->SiS_Pr.SiS_CHOverScan = -1; 5842 ivideo->SiS_Pr.SiS_ChSW = false; 5843 ivideo->SiS_Pr.SiS_UseLCDA = false; 5844 ivideo->SiS_Pr.HaveEMI = false; 5845 ivideo->SiS_Pr.HaveEMILCD = false; 5846 ivideo->SiS_Pr.OverruleEMI = false; 5847 ivideo->SiS_Pr.SiS_SensibleSR11 = false; 5848 ivideo->SiS_Pr.SiS_MyCR63 = 0x63; 5849 ivideo->SiS_Pr.PDC = -1; 5850 ivideo->SiS_Pr.PDCA = -1; 5851 ivideo->SiS_Pr.DDCPortMixup = false; 5852#ifdef CONFIG_FB_SIS_315 5853 if(ivideo->chip >= SIS_330) { 5854 ivideo->SiS_Pr.SiS_MyCR63 = 0x53; 5855 if(ivideo->chip >= SIS_661) { 5856 ivideo->SiS_Pr.SiS_SensibleSR11 = true; 5857 } 5858 } 5859#endif 5860 5861 memcpy(&ivideo->default_var, &my_default_var, sizeof(my_default_var)); 5862 5863 pci_set_drvdata(pdev, ivideo); 5864 5865 /* Patch special cases */ 5866 if((ivideo->nbridge = sisfb_get_northbridge(ivideo->chip))) { 5867 switch(ivideo->nbridge->device) { 5868#ifdef CONFIG_FB_SIS_300 5869 case PCI_DEVICE_ID_SI_730: 5870 ivideo->chip = SIS_730; 5871 strcpy(ivideo->myid, "SiS 730"); 5872 break; 5873#endif 5874#ifdef CONFIG_FB_SIS_315 5875 case PCI_DEVICE_ID_SI_651: 5876 /* ivideo->chip is ok */ 5877 strcpy(ivideo->myid, "SiS 651"); 5878 break; 5879 case PCI_DEVICE_ID_SI_740: 5880 ivideo->chip = SIS_740; 5881 strcpy(ivideo->myid, "SiS 740"); 5882 break; 5883 case PCI_DEVICE_ID_SI_661: 5884 ivideo->chip = SIS_661; 5885 strcpy(ivideo->myid, "SiS 661"); 5886 break; 5887 case PCI_DEVICE_ID_SI_741: 5888 ivideo->chip = SIS_741; 5889 strcpy(ivideo->myid, "SiS 741"); 5890 break; 5891 case PCI_DEVICE_ID_SI_760: 5892 ivideo->chip = SIS_760; 5893 strcpy(ivideo->myid, "SiS 760"); 5894 break; 5895 case PCI_DEVICE_ID_SI_761: 5896 ivideo->chip = SIS_761; 5897 strcpy(ivideo->myid, "SiS 761"); 5898 break; 5899#endif 5900 default: 5901 break; 5902 } 5903 } 5904 5905 ivideo->SiS_Pr.ChipType = ivideo->chip; 5906 5907 ivideo->SiS_Pr.ivideo = (void *)ivideo; 5908 5909#ifdef CONFIG_FB_SIS_315 5910 if((ivideo->SiS_Pr.ChipType == SIS_315PRO) || 5911 (ivideo->SiS_Pr.ChipType == SIS_315)) { 5912 ivideo->SiS_Pr.ChipType = SIS_315H; 5913 } 5914#endif 5915 5916 if(!ivideo->sisvga_enabled) { 5917 if(pci_enable_device(pdev)) { 5918 if(ivideo->nbridge) pci_dev_put(ivideo->nbridge); 5919 pci_set_drvdata(pdev, NULL); 5920 kfree(sis_fb_info); 5921 return -EIO; 5922 } 5923 } 5924 5925 ivideo->video_base = pci_resource_start(pdev, 0); 5926 ivideo->mmio_base = pci_resource_start(pdev, 1); 5927 ivideo->mmio_size = pci_resource_len(pdev, 1); 5928 ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30; 5929 ivideo->SiS_Pr.IOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO; 5930 5931 SiSRegInit(&ivideo->SiS_Pr, ivideo->SiS_Pr.IOAddress); 5932 5933#ifdef CONFIG_FB_SIS_300 5934 /* Find PCI systems for Chrontel/GPIO communication setup */ 5935 if(ivideo->chip == SIS_630) { 5936 i = 0; 5937 do { 5938 if(mychswtable[i].subsysVendor == ivideo->subsysvendor && 5939 mychswtable[i].subsysCard == ivideo->subsysdevice) { 5940 ivideo->SiS_Pr.SiS_ChSW = true; 5941 printk(KERN_DEBUG "sisfb: Identified [%s %s] " 5942 "requiring Chrontel/GPIO setup\n", 5943 mychswtable[i].vendorName, 5944 mychswtable[i].cardName); 5945 ivideo->lpcdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0008, NULL); 5946 break; 5947 } 5948 i++; 5949 } while(mychswtable[i].subsysVendor != 0); 5950 } 5951#endif 5952 5953#ifdef CONFIG_FB_SIS_315 5954 if((ivideo->chip == SIS_760) && (ivideo->nbridge)) { 5955 ivideo->lpcdev = pci_get_slot(ivideo->nbridge->bus, (2 << 3)); 5956 } 5957#endif 5958 5959 outSISIDXREG(SISSR, 0x05, 0x86); 5960 5961 if( (!ivideo->sisvga_enabled) 5962#if !defined(__i386__) && !defined(__x86_64__) 5963 || (sisfb_resetcard) 5964#endif 5965 ) { 5966 for(i = 0x30; i <= 0x3f; i++) { 5967 outSISIDXREG(SISCR, i, 0x00); 5968 } 5969 } 5970 5971 /* Find out about current video mode */ 5972 ivideo->modeprechange = 0x03; 5973 inSISIDXREG(SISCR, 0x34, reg); 5974 if(reg & 0x7f) { 5975 ivideo->modeprechange = reg & 0x7f; 5976 } else if(ivideo->sisvga_enabled) { 5977#if defined(__i386__) || defined(__x86_64__) 5978 unsigned char SIS_IOTYPE2 *tt = ioremap(0x400, 0x100); 5979 if(tt) { 5980 ivideo->modeprechange = readb(tt + 0x49); 5981 iounmap(tt); 5982 } 5983#endif 5984 } 5985 5986 /* Search and copy ROM image */ 5987 ivideo->bios_abase = NULL; 5988 ivideo->SiS_Pr.VirtualRomBase = NULL; 5989 ivideo->SiS_Pr.UseROM = false; 5990 ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = false; 5991 if(ivideo->sisfb_userom) { 5992 ivideo->SiS_Pr.VirtualRomBase = sisfb_find_rom(pdev); 5993 ivideo->bios_abase = ivideo->SiS_Pr.VirtualRomBase; 5994 ivideo->SiS_Pr.UseROM = (bool)(ivideo->SiS_Pr.VirtualRomBase); 5995 printk(KERN_INFO "sisfb: Video ROM %sfound\n", 5996 ivideo->SiS_Pr.UseROM ? "" : "not "); 5997 if((ivideo->SiS_Pr.UseROM) && (ivideo->chip >= XGI_20)) { 5998 ivideo->SiS_Pr.UseROM = false; 5999 ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = true; 6000 if( (ivideo->revision_id == 2) && 6001 (!(ivideo->bios_abase[0x1d1] & 0x01)) ) { 6002 ivideo->SiS_Pr.DDCPortMixup = true; 6003 } 6004 } 6005 } else { 6006 printk(KERN_INFO "sisfb: Video ROM usage disabled\n"); 6007 } 6008 6009 /* Find systems for special custom timing */ 6010 if(ivideo->SiS_Pr.SiS_CustomT == CUT_NONE) { 6011 sisfb_detect_custom_timing(ivideo); 6012 } 6013 6014 /* POST card in case this has not been done by the BIOS */ 6015 if( (!ivideo->sisvga_enabled) 6016#if !defined(__i386__) && !defined(__x86_64__) 6017 || (sisfb_resetcard) 6018#endif 6019 ) { 6020#ifdef CONFIG_FB_SIS_300 6021 if(ivideo->sisvga_engine == SIS_300_VGA) { 6022 if(ivideo->chip == SIS_300) { 6023 sisfb_post_sis300(pdev); 6024 ivideo->sisfb_can_post = 1; 6025 } 6026 } 6027#endif 6028 6029#ifdef CONFIG_FB_SIS_315 6030 if(ivideo->sisvga_engine == SIS_315_VGA) { 6031 int result = 1; 6032 /* if((ivideo->chip == SIS_315H) || 6033 (ivideo->chip == SIS_315) || 6034 (ivideo->chip == SIS_315PRO) || 6035 (ivideo->chip == SIS_330)) { 6036 sisfb_post_sis315330(pdev); 6037 } else */ if(ivideo->chip == XGI_20) { 6038 result = sisfb_post_xgi(pdev); 6039 ivideo->sisfb_can_post = 1; 6040 } else if((ivideo->chip == XGI_40) && ivideo->haveXGIROM) { 6041 result = sisfb_post_xgi(pdev); 6042 ivideo->sisfb_can_post = 1; 6043 } else { 6044 printk(KERN_INFO "sisfb: Card is not " 6045 "POSTed and sisfb can't do this either.\n"); 6046 } 6047 if(!result) { 6048 printk(KERN_ERR "sisfb: Failed to POST card\n"); 6049 ret = -ENODEV; 6050 goto error_3; 6051 } 6052 } 6053#endif 6054 } 6055 6056 ivideo->sisfb_card_posted = 1; 6057 6058 /* Find out about RAM size */ 6059 if(sisfb_get_dram_size(ivideo)) { 6060 printk(KERN_INFO "sisfb: Fatal error: Unable to determine VRAM size.\n"); 6061 ret = -ENODEV; 6062 goto error_3; 6063 } 6064 6065 6066 /* Enable PCI addressing and MMIO */ 6067 if((ivideo->sisfb_mode_idx < 0) || 6068 ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) { 6069 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */ 6070 orSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE)); 6071 /* Enable 2D accelerator engine */ 6072 orSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D); 6073 } 6074 6075 if(sisfb_pdc != 0xff) { 6076 if(ivideo->sisvga_engine == SIS_300_VGA) 6077 sisfb_pdc &= 0x3c; 6078 else 6079 sisfb_pdc &= 0x1f; 6080 ivideo->SiS_Pr.PDC = sisfb_pdc; 6081 } 6082#ifdef CONFIG_FB_SIS_315 6083 if(ivideo->sisvga_engine == SIS_315_VGA) { 6084 if(sisfb_pdca != 0xff) 6085 ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f; 6086 } 6087#endif 6088 6089 if(!request_mem_region(ivideo->video_base, ivideo->video_size, "sisfb FB")) { 6090 printk(KERN_ERR "sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n", 6091 (int)(ivideo->video_size >> 20)); 6092 printk(KERN_ERR "sisfb: Is there another framebuffer driver active?\n"); 6093 ret = -ENODEV; 6094 goto error_3; 6095 } 6096 6097 if(!request_mem_region(ivideo->mmio_base, ivideo->mmio_size, "sisfb MMIO")) { 6098 printk(KERN_ERR "sisfb: Fatal error: Unable to reserve MMIO region\n"); 6099 ret = -ENODEV; 6100 goto error_2; 6101 } 6102 6103 ivideo->video_vbase = ioremap(ivideo->video_base, ivideo->video_size); 6104 ivideo->SiS_Pr.VideoMemoryAddress = ivideo->video_vbase; 6105 if(!ivideo->video_vbase) { 6106 printk(KERN_ERR "sisfb: Fatal error: Unable to map framebuffer memory\n"); 6107 ret = -ENODEV; 6108 goto error_1; 6109 } 6110 6111 ivideo->mmio_vbase = ioremap(ivideo->mmio_base, ivideo->mmio_size); 6112 if(!ivideo->mmio_vbase) { 6113 printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n"); 6114 ret = -ENODEV; 6115error_0: iounmap(ivideo->video_vbase); 6116error_1: release_mem_region(ivideo->video_base, ivideo->video_size); 6117error_2: release_mem_region(ivideo->mmio_base, ivideo->mmio_size); 6118error_3: vfree(ivideo->bios_abase); 6119 if(ivideo->lpcdev) 6120 pci_dev_put(ivideo->lpcdev); 6121 if(ivideo->nbridge) 6122 pci_dev_put(ivideo->nbridge); 6123 pci_set_drvdata(pdev, NULL); 6124 if(!ivideo->sisvga_enabled) 6125 pci_disable_device(pdev); 6126 kfree(sis_fb_info); 6127 return ret; 6128 } 6129 6130 printk(KERN_INFO "sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n", 6131 ivideo->video_base, (unsigned long)ivideo->video_vbase, ivideo->video_size / 1024); 6132 6133 if(ivideo->video_offset) { 6134 printk(KERN_INFO "sisfb: Viewport offset %ldk\n", 6135 ivideo->video_offset / 1024); 6136 } 6137 6138 printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n", 6139 ivideo->mmio_base, (unsigned long)ivideo->mmio_vbase, ivideo->mmio_size / 1024); 6140 6141 6142 /* Determine the size of the command queue */ 6143 if(ivideo->sisvga_engine == SIS_300_VGA) { 6144 ivideo->cmdQueueSize = TURBO_QUEUE_AREA_SIZE; 6145 } else { 6146 if(ivideo->chip == XGI_20) { 6147 ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE_Z7; 6148 } else { 6149 ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE; 6150 } 6151 } 6152 6153 /* Engines are no longer initialized here; this is 6154 * now done after the first mode-switch (if the 6155 * submitted var has its acceleration flags set). 6156 */ 6157 6158 /* Calculate the base of the (unused) hw cursor */ 6159 ivideo->hwcursor_vbase = ivideo->video_vbase 6160 + ivideo->video_size 6161 - ivideo->cmdQueueSize 6162 - ivideo->hwcursor_size; 6163 ivideo->caps |= HW_CURSOR_CAP; 6164 6165 /* Initialize offscreen memory manager */ 6166 if((ivideo->havenoheap = sisfb_heap_init(ivideo))) { 6167 printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heap\n"); 6168 } 6169 6170 /* Used for clearing the screen only, therefore respect our mem limit */ 6171 ivideo->SiS_Pr.VideoMemoryAddress += ivideo->video_offset; 6172 ivideo->SiS_Pr.VideoMemorySize = ivideo->sisfb_mem; 6173 6174 ivideo->mtrr = -1; 6175 6176 ivideo->vbflags = 0; 6177 ivideo->lcddefmodeidx = DEFAULT_LCDMODE; 6178 ivideo->tvdefmodeidx = DEFAULT_TVMODE; 6179 ivideo->defmodeidx = DEFAULT_MODE; 6180 6181 ivideo->newrom = 0; 6182 if(ivideo->chip < XGI_20) { 6183 if(ivideo->bios_abase) { 6184 ivideo->newrom = SiSDetermineROMLayout661(&ivideo->SiS_Pr); 6185 } 6186 } 6187 6188 if((ivideo->sisfb_mode_idx < 0) || 6189 ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) { 6190 6191 sisfb_sense_crt1(ivideo); 6192 6193 sisfb_get_VB_type(ivideo); 6194 6195 if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) { 6196 sisfb_detect_VB_connect(ivideo); 6197 } 6198 6199 ivideo->currentvbflags = ivideo->vbflags & (VB_VIDEOBRIDGE | TV_STANDARD); 6200 6201 /* Decide on which CRT2 device to use */ 6202 if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) { 6203 if(ivideo->sisfb_crt2type != -1) { 6204 if((ivideo->sisfb_crt2type == CRT2_LCD) && 6205 (ivideo->vbflags & CRT2_LCD)) { 6206 ivideo->currentvbflags |= CRT2_LCD; 6207 } else if(ivideo->sisfb_crt2type != CRT2_LCD) { 6208 ivideo->currentvbflags |= ivideo->sisfb_crt2type; 6209 } 6210 } else { 6211 /* Chrontel 700x TV detection often unreliable, therefore 6212 * use a different default order on such machines 6213 */ 6214 if((ivideo->sisvga_engine == SIS_300_VGA) && 6215 (ivideo->vbflags2 & VB2_CHRONTEL)) { 6216 if(ivideo->vbflags & CRT2_LCD) 6217 ivideo->currentvbflags |= CRT2_LCD; 6218 else if(ivideo->vbflags & CRT2_TV) 6219 ivideo->currentvbflags |= CRT2_TV; 6220 else if(ivideo->vbflags & CRT2_VGA) 6221 ivideo->currentvbflags |= CRT2_VGA; 6222 } else { 6223 if(ivideo->vbflags & CRT2_TV) 6224 ivideo->currentvbflags |= CRT2_TV; 6225 else if(ivideo->vbflags & CRT2_LCD) 6226 ivideo->currentvbflags |= CRT2_LCD; 6227 else if(ivideo->vbflags & CRT2_VGA) 6228 ivideo->currentvbflags |= CRT2_VGA; 6229 } 6230 } 6231 } 6232 6233 if(ivideo->vbflags & CRT2_LCD) { 6234 sisfb_detect_lcd_type(ivideo); 6235 } 6236 6237 sisfb_save_pdc_emi(ivideo); 6238 6239 if(!ivideo->sisfb_crt1off) { 6240 sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 0); 6241 } else { 6242 if((ivideo->vbflags2 & VB2_SISTMDSBRIDGE) && 6243 (ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) { 6244 sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 1); 6245 } 6246 } 6247 6248 if(ivideo->sisfb_mode_idx >= 0) { 6249 int bu = ivideo->sisfb_mode_idx; 6250 ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo, 6251 ivideo->sisfb_mode_idx, ivideo->currentvbflags); 6252 if(bu != ivideo->sisfb_mode_idx) { 6253 printk(KERN_ERR "Mode %dx%dx%d failed validation\n", 6254 sisbios_mode[bu].xres, 6255 sisbios_mode[bu].yres, 6256 sisbios_mode[bu].bpp); 6257 } 6258 } 6259 6260 if(ivideo->sisfb_mode_idx < 0) { 6261 switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) { 6262 case CRT2_LCD: 6263 ivideo->sisfb_mode_idx = ivideo->lcddefmodeidx; 6264 break; 6265 case CRT2_TV: 6266 ivideo->sisfb_mode_idx = ivideo->tvdefmodeidx; 6267 break; 6268 default: 6269 ivideo->sisfb_mode_idx = ivideo->defmodeidx; 6270 break; 6271 } 6272 } 6273 6274 ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]; 6275 6276 if(ivideo->refresh_rate != 0) { 6277 sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, 6278 ivideo->sisfb_mode_idx); 6279 } 6280 6281 if(ivideo->rate_idx == 0) { 6282 ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx; 6283 ivideo->refresh_rate = 60; 6284 } 6285 6286 if(ivideo->sisfb_thismonitor.datavalid) { 6287 if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, 6288 ivideo->sisfb_mode_idx, 6289 ivideo->rate_idx, 6290 ivideo->refresh_rate)) { 6291 printk(KERN_INFO "sisfb: WARNING: Refresh rate " 6292 "exceeds monitor specs!\n"); 6293 } 6294 } 6295 6296 ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp; 6297 ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres; 6298 ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres; 6299 6300 sisfb_set_vparms(ivideo); 6301 6302 printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n", 6303 ivideo->video_width, ivideo->video_height, ivideo->video_bpp, 6304 ivideo->refresh_rate); 6305 6306 /* Set up the default var according to chosen default display mode */ 6307 ivideo->default_var.xres = ivideo->default_var.xres_virtual = ivideo->video_width; 6308 ivideo->default_var.yres = ivideo->default_var.yres_virtual = ivideo->video_height; 6309 ivideo->default_var.bits_per_pixel = ivideo->video_bpp; 6310 6311 sisfb_bpp_to_var(ivideo, &ivideo->default_var); 6312 6313 ivideo->default_var.pixclock = (u32) (1000000000 / 6314 sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, ivideo->mode_no, ivideo->rate_idx)); 6315 6316 if(sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, ivideo->mode_no, 6317 ivideo->rate_idx, &ivideo->default_var)) { 6318 if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) { 6319 ivideo->default_var.pixclock <<= 1; 6320 } 6321 } 6322 6323 if(ivideo->sisfb_ypan) { 6324 /* Maximize regardless of sisfb_max at startup */ 6325 ivideo->default_var.yres_virtual = 6326 sisfb_calc_maxyres(ivideo, &ivideo->default_var); 6327 if(ivideo->default_var.yres_virtual < ivideo->default_var.yres) { 6328 ivideo->default_var.yres_virtual = ivideo->default_var.yres; 6329 } 6330 } 6331 6332 sisfb_calc_pitch(ivideo, &ivideo->default_var); 6333 6334 ivideo->accel = 0; 6335 if(ivideo->sisfb_accel) { 6336 ivideo->accel = -1; 6337#ifdef STUPID_ACCELF_TEXT_SHIT 6338 ivideo->default_var.accel_flags |= FB_ACCELF_TEXT; 6339#endif 6340 } 6341 sisfb_initaccel(ivideo); 6342 6343#if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN) 6344 sis_fb_info->flags = FBINFO_DEFAULT | 6345 FBINFO_HWACCEL_YPAN | 6346 FBINFO_HWACCEL_XPAN | 6347 FBINFO_HWACCEL_COPYAREA | 6348 FBINFO_HWACCEL_FILLRECT | 6349 ((ivideo->accel) ? 0 : FBINFO_HWACCEL_DISABLED); 6350#else 6351 sis_fb_info->flags = FBINFO_FLAG_DEFAULT; 6352#endif 6353 sis_fb_info->var = ivideo->default_var; 6354 sis_fb_info->fix = ivideo->sisfb_fix; 6355 sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset; 6356 sis_fb_info->fbops = &sisfb_ops; 6357 sisfb_get_fix(&sis_fb_info->fix, -1, sis_fb_info); 6358 sis_fb_info->pseudo_palette = ivideo->pseudo_palette; 6359 6360 fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0); 6361 6362 printk(KERN_DEBUG "sisfb: Initial vbflags 0x%x\n", (int)ivideo->vbflags); 6363 6364#ifdef CONFIG_MTRR 6365 ivideo->mtrr = mtrr_add(ivideo->video_base, ivideo->video_size, 6366 MTRR_TYPE_WRCOMB, 1); 6367 if(ivideo->mtrr < 0) { 6368 printk(KERN_DEBUG "sisfb: Failed to add MTRRs\n"); 6369 } 6370#endif 6371 6372 if(register_framebuffer(sis_fb_info) < 0) { 6373 printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n"); 6374 ret = -EINVAL; 6375 iounmap(ivideo->mmio_vbase); 6376 goto error_0; 6377 } 6378 6379 ivideo->registered = 1; 6380 6381 /* Enlist us */ 6382 ivideo->next = card_list; 6383 card_list = ivideo; 6384 6385#ifdef SIS_OLD_CONFIG_COMPAT 6386 { 6387 int ret; 6388 /* Our ioctls are all "32/64bit compatible" */ 6389 ret = register_ioctl32_conversion(FBIO_ALLOC, NULL); 6390 ret |= register_ioctl32_conversion(FBIO_FREE, NULL); 6391 ret |= register_ioctl32_conversion(FBIOGET_VBLANK, NULL); 6392 ret |= register_ioctl32_conversion(SISFB_GET_INFO_SIZE, NULL); 6393 ret |= register_ioctl32_conversion(SISFB_GET_INFO, NULL); 6394 ret |= register_ioctl32_conversion(SISFB_GET_TVPOSOFFSET, NULL); 6395 ret |= register_ioctl32_conversion(SISFB_SET_TVPOSOFFSET, NULL); 6396 ret |= register_ioctl32_conversion(SISFB_SET_LOCK, NULL); 6397 ret |= register_ioctl32_conversion(SISFB_GET_VBRSTATUS, NULL); 6398 ret |= register_ioctl32_conversion(SISFB_GET_AUTOMAXIMIZE, NULL); 6399 ret |= register_ioctl32_conversion(SISFB_SET_AUTOMAXIMIZE, NULL); 6400 ret |= register_ioctl32_conversion(SISFB_COMMAND, NULL); 6401 if(ret) 6402 printk(KERN_ERR 6403 "sisfb: Error registering ioctl32 translations\n"); 6404 else 6405 ivideo->ioctl32registered = 1; 6406 } 6407#endif 6408 6409 printk(KERN_INFO "sisfb: 2D acceleration is %s, y-panning %s\n", 6410 ivideo->sisfb_accel ? "enabled" : "disabled", 6411 ivideo->sisfb_ypan ? 6412 (ivideo->sisfb_max ? "enabled (auto-max)" : 6413 "enabled (no auto-max)") : 6414 "disabled"); 6415 6416 6417 printk(KERN_INFO "fb%d: %s frame buffer device version %d.%d.%d\n", 6418 sis_fb_info->node, ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL); 6419 6420 printk(KERN_INFO "sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n"); 6421 6422 } /* if mode = "none" */ 6423 6424 return 0; 6425} 6426 6427/*****************************************************/ 6428/* PCI DEVICE HANDLING */ 6429/*****************************************************/ 6430 6431static void __devexit sisfb_remove(struct pci_dev *pdev) 6432{ 6433 struct sis_video_info *ivideo = pci_get_drvdata(pdev); 6434 struct fb_info *sis_fb_info = ivideo->memyselfandi; 6435 int registered = ivideo->registered; 6436 int modechanged = ivideo->modechanged; 6437 6438#ifdef SIS_OLD_CONFIG_COMPAT 6439 if(ivideo->ioctl32registered) { 6440 int ret; 6441 ret = unregister_ioctl32_conversion(FBIO_ALLOC); 6442 ret |= unregister_ioctl32_conversion(FBIO_FREE); 6443 ret |= unregister_ioctl32_conversion(FBIOGET_VBLANK); 6444 ret |= unregister_ioctl32_conversion(SISFB_GET_INFO_SIZE); 6445 ret |= unregister_ioctl32_conversion(SISFB_GET_INFO); 6446 ret |= unregister_ioctl32_conversion(SISFB_GET_TVPOSOFFSET); 6447 ret |= unregister_ioctl32_conversion(SISFB_SET_TVPOSOFFSET); 6448 ret |= unregister_ioctl32_conversion(SISFB_SET_LOCK); 6449 ret |= unregister_ioctl32_conversion(SISFB_GET_VBRSTATUS); 6450 ret |= unregister_ioctl32_conversion(SISFB_GET_AUTOMAXIMIZE); 6451 ret |= unregister_ioctl32_conversion(SISFB_SET_AUTOMAXIMIZE); 6452 ret |= unregister_ioctl32_conversion(SISFB_COMMAND); 6453 if(ret) 6454 printk(KERN_ERR 6455 "sisfb: Error unregistering ioctl32 translations\n"); 6456 } 6457#endif 6458 6459 /* Unmap */ 6460 iounmap(ivideo->mmio_vbase); 6461 iounmap(ivideo->video_vbase); 6462 6463 /* Release mem regions */ 6464 release_mem_region(ivideo->video_base, ivideo->video_size); 6465 release_mem_region(ivideo->mmio_base, ivideo->mmio_size); 6466 6467 vfree(ivideo->bios_abase); 6468 6469 if(ivideo->lpcdev) 6470 pci_dev_put(ivideo->lpcdev); 6471 6472 if(ivideo->nbridge) 6473 pci_dev_put(ivideo->nbridge); 6474 6475#ifdef CONFIG_MTRR 6476 /* Release MTRR region */ 6477 if(ivideo->mtrr >= 0) 6478 mtrr_del(ivideo->mtrr, ivideo->video_base, ivideo->video_size); 6479#endif 6480 6481 pci_set_drvdata(pdev, NULL); 6482 6483 /* If device was disabled when starting, disable 6484 * it when quitting. 6485 */ 6486 if(!ivideo->sisvga_enabled) 6487 pci_disable_device(pdev); 6488 6489 /* Unregister the framebuffer */ 6490 if(ivideo->registered) { 6491 unregister_framebuffer(sis_fb_info); 6492 framebuffer_release(sis_fb_info); 6493 } 6494 6495 /* OK, our ivideo is gone for good from here. */ 6496 6497 /* TODO: Restore the initial mode 6498 * This sounds easy but is as good as impossible 6499 * on many machines with SiS chip and video bridge 6500 * since text modes are always set up differently 6501 * from machine to machine. Depends on the type 6502 * of integration between chipset and bridge. 6503 */ 6504 if(registered && modechanged) 6505 printk(KERN_INFO 6506 "sisfb: Restoring of text mode not supported yet\n"); 6507}; 6508 6509static struct pci_driver sisfb_driver = { 6510 .name = "sisfb", 6511 .id_table = sisfb_pci_table, 6512 .probe = sisfb_probe, 6513 .remove = __devexit_p(sisfb_remove) 6514}; 6515 6516SISINITSTATIC int __init sisfb_init(void) 6517{ 6518#ifndef MODULE 6519 char *options = NULL; 6520 6521 if(fb_get_options("sisfb", &options)) 6522 return -ENODEV; 6523 6524 sisfb_setup(options); 6525#endif 6526 return pci_register_driver(&sisfb_driver); 6527} 6528 6529#ifndef MODULE 6530module_init(sisfb_init); 6531#endif 6532 6533/*****************************************************/ 6534/* MODULE */ 6535/*****************************************************/ 6536 6537#ifdef MODULE 6538 6539static char *mode = NULL; 6540static int vesa = -1; 6541static unsigned int rate = 0; 6542static unsigned int crt1off = 1; 6543static unsigned int mem = 0; 6544static char *forcecrt2type = NULL; 6545static int forcecrt1 = -1; 6546static int pdc = -1; 6547static int pdc1 = -1; 6548static int noaccel = -1; 6549static int noypan = -1; 6550static int nomax = -1; 6551static int userom = -1; 6552static int useoem = -1; 6553static char *tvstandard = NULL; 6554static int nocrt2rate = 0; 6555static int scalelcd = -1; 6556static char *specialtiming = NULL; 6557static int lvdshl = -1; 6558static int tvxposoffset = 0, tvyposoffset = 0; 6559#if !defined(__i386__) && !defined(__x86_64__) 6560static int resetcard = 0; 6561static int videoram = 0; 6562#endif 6563 6564static int __init sisfb_init_module(void) 6565{ 6566 sisfb_setdefaultparms(); 6567 6568 if(rate) 6569 sisfb_parm_rate = rate; 6570 6571 if((scalelcd == 0) || (scalelcd == 1)) 6572 sisfb_scalelcd = scalelcd ^ 1; 6573 6574 /* Need to check crt2 type first for fstn/dstn */ 6575 6576 if(forcecrt2type) 6577 sisfb_search_crt2type(forcecrt2type); 6578 6579 if(tvstandard) 6580 sisfb_search_tvstd(tvstandard); 6581 6582 if(mode) 6583 sisfb_search_mode(mode, false); 6584 else if(vesa != -1) 6585 sisfb_search_vesamode(vesa, false); 6586 6587 sisfb_crt1off = (crt1off == 0) ? 1 : 0; 6588 6589 sisfb_forcecrt1 = forcecrt1; 6590 if(forcecrt1 == 1) 6591 sisfb_crt1off = 0; 6592 else if(forcecrt1 == 0) 6593 sisfb_crt1off = 1; 6594 6595 if(noaccel == 1) 6596 sisfb_accel = 0; 6597 else if(noaccel == 0) 6598 sisfb_accel = 1; 6599 6600 if(noypan == 1) 6601 sisfb_ypan = 0; 6602 else if(noypan == 0) 6603 sisfb_ypan = 1; 6604 6605 if(nomax == 1) 6606 sisfb_max = 0; 6607 else if(nomax == 0) 6608 sisfb_max = 1; 6609 6610 if(mem) 6611 sisfb_parm_mem = mem; 6612 6613 if(userom != -1) 6614 sisfb_userom = userom; 6615 6616 if(useoem != -1) 6617 sisfb_useoem = useoem; 6618 6619 if(pdc != -1) 6620 sisfb_pdc = (pdc & 0x7f); 6621 6622 if(pdc1 != -1) 6623 sisfb_pdca = (pdc1 & 0x1f); 6624 6625 sisfb_nocrt2rate = nocrt2rate; 6626 6627 if(specialtiming) 6628 sisfb_search_specialtiming(specialtiming); 6629 6630 if((lvdshl >= 0) && (lvdshl <= 3)) 6631 sisfb_lvdshl = lvdshl; 6632 6633 sisfb_tvxposoffset = tvxposoffset; 6634 sisfb_tvyposoffset = tvyposoffset; 6635 6636#if !defined(__i386__) && !defined(__x86_64__) 6637 sisfb_resetcard = (resetcard) ? 1 : 0; 6638 if(videoram) 6639 sisfb_videoram = videoram; 6640#endif 6641 6642 return sisfb_init(); 6643} 6644 6645static void __exit sisfb_remove_module(void) 6646{ 6647 pci_unregister_driver(&sisfb_driver); 6648 printk(KERN_DEBUG "sisfb: Module unloaded\n"); 6649} 6650 6651module_init(sisfb_init_module); 6652module_exit(sisfb_remove_module); 6653 6654MODULE_DESCRIPTION("SiS 300/540/630/730/315/55x/65x/661/74x/330/76x/34x, XGI V3XT/V5/V8/Z7 framebuffer device driver"); 6655MODULE_LICENSE("GPL"); 6656MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others"); 6657 6658module_param(mem, int, 0); 6659module_param(noaccel, int, 0); 6660module_param(noypan, int, 0); 6661module_param(nomax, int, 0); 6662module_param(userom, int, 0); 6663module_param(useoem, int, 0); 6664module_param(mode, charp, 0); 6665module_param(vesa, int, 0); 6666module_param(rate, int, 0); 6667module_param(forcecrt1, int, 0); 6668module_param(forcecrt2type, charp, 0); 6669module_param(scalelcd, int, 0); 6670module_param(pdc, int, 0); 6671module_param(pdc1, int, 0); 6672module_param(specialtiming, charp, 0); 6673module_param(lvdshl, int, 0); 6674module_param(tvstandard, charp, 0); 6675module_param(tvxposoffset, int, 0); 6676module_param(tvyposoffset, int, 0); 6677module_param(nocrt2rate, int, 0); 6678#if !defined(__i386__) && !defined(__x86_64__) 6679module_param(resetcard, int, 0); 6680module_param(videoram, int, 0); 6681#endif 6682 6683MODULE_PARM_DESC(mem, 6684 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n" 6685 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n" 6686 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n" 6687 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n" 6688 "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n" 6689 "The value is to be specified without 'KB'.\n"); 6690 6691MODULE_PARM_DESC(noaccel, 6692 "\nIf set to anything other than 0, 2D acceleration will be disabled.\n" 6693 "(default: 0)\n"); 6694 6695MODULE_PARM_DESC(noypan, 6696 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n" 6697 "will be performed by redrawing the screen. (default: 0)\n"); 6698 6699MODULE_PARM_DESC(nomax, 6700 "\nIf y-panning is enabled, sisfb will by default use the entire available video\n" 6701 "memory for the virtual screen in order to optimize scrolling performance. If\n" 6702 "this is set to anything other than 0, sisfb will not do this and thereby \n" 6703 "enable the user to positively specify a virtual Y size of the screen using\n" 6704 "fbset. (default: 0)\n"); 6705 6706MODULE_PARM_DESC(mode, 6707 "\nSelects the desired default display mode in the format XxYxDepth,\n" 6708 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n" 6709 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n" 6710 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n"); 6711 6712MODULE_PARM_DESC(vesa, 6713 "\nSelects the desired default display mode by VESA defined mode number, eg.\n" 6714 "0x117 (default: 0x0103)\n"); 6715 6716MODULE_PARM_DESC(rate, 6717 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n" 6718 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n" 6719 "will be ignored (default: 60)\n"); 6720 6721MODULE_PARM_DESC(forcecrt1, 6722 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n" 6723 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n" 6724 "0=CRT1 OFF) (default: [autodetected])\n"); 6725 6726MODULE_PARM_DESC(forcecrt2type, 6727 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n" 6728 "LCD, TV or secondary VGA. With this option, this autodetection can be\n" 6729 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n" 6730 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n" 6731 "be used instead of TV to override the TV detection. Furthermore, on systems\n" 6732 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n" 6733 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n" 6734 "depends on the very hardware in use. (default: [autodetected])\n"); 6735 6736MODULE_PARM_DESC(scalelcd, 6737 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n" 6738 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n" 6739 "show black bars around the image, TMDS panels will probably do the scaling\n" 6740 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n"); 6741 6742MODULE_PARM_DESC(pdc, 6743 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n" 6744 "should detect this correctly in most cases; however, sometimes this is not\n" 6745 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n" 6746 "on a 300 series chipset; 6 on other chipsets. If the problem persists, try\n" 6747 "other values (on 300 series: between 4 and 60 in steps of 4; otherwise: any\n" 6748 "value from 0 to 31). (default: autodetected, if LCD is active during start)\n"); 6749 6750#ifdef CONFIG_FB_SIS_315 6751MODULE_PARM_DESC(pdc1, 6752 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330/340\n" 6753 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n" 6754 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n" 6755 "implemented yet.\n"); 6756#endif 6757 6758MODULE_PARM_DESC(specialtiming, 6759 "\nPlease refer to documentation for more information on this option.\n"); 6760 6761MODULE_PARM_DESC(lvdshl, 6762 "\nPlease refer to documentation for more information on this option.\n"); 6763 6764MODULE_PARM_DESC(tvstandard, 6765 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n" 6766 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n"); 6767 6768MODULE_PARM_DESC(tvxposoffset, 6769 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n" 6770 "Default: 0\n"); 6771 6772MODULE_PARM_DESC(tvyposoffset, 6773 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n" 6774 "Default: 0\n"); 6775 6776MODULE_PARM_DESC(nocrt2rate, 6777 "\nSetting this to 1 will force the driver to use the default refresh rate for\n" 6778 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n"); 6779 6780#if !defined(__i386__) && !defined(__x86_64__) 6781#ifdef CONFIG_FB_SIS_300 6782MODULE_PARM_DESC(resetcard, 6783 "\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n" 6784 "the BIOS did not POST the card (only supported for SiS 300/305 and XGI cards\n" 6785 "currently). Default: 0\n"); 6786 6787MODULE_PARM_DESC(videoram, 6788 "\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n" 6789 "some non-x86 architectures where the memory auto detection fails. Only\n" 6790 "relevant if resetcard is set, too. SiS300/305 only. Default: [auto-detect]\n"); 6791#endif 6792#endif 6793 6794#endif /* /MODULE */ 6795 6796/* _GPL only for new symbols. */ 6797EXPORT_SYMBOL(sis_malloc); 6798EXPORT_SYMBOL(sis_free); 6799EXPORT_SYMBOL_GPL(sis_malloc_new); 6800EXPORT_SYMBOL_GPL(sis_free_new); 6801