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