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