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