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