nv_setup.c revision 6257f37d
1/* 2 * Copyright (c) 2003 NVIDIA, Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the 6 * "Software"), to deal in the Software without restriction, including 7 * without limitation the rights to use, copy, modify, merge, publish, 8 * distribute, sublicense, and/or sell copies of the Software, and to 9 * permit persons to whom the Software is furnished to do so, subject to 10 * the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included 13 * in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 */ 23 24#ifdef HAVE_CONFIG_H 25#include "config.h" 26#endif 27 28#include "nv_include.h" 29 30/* 31 * Override VGA I/O routines. 32 */ 33static void NVWriteCrtc(vgaHWPtr pVga, CARD8 index, CARD8 value) 34{ 35 NVPtr pNv = (NVPtr)pVga->MMIOBase; 36 VGA_WR08(pNv->PCIO, pVga->IOBase + VGA_CRTC_INDEX_OFFSET, index); 37 VGA_WR08(pNv->PCIO, pVga->IOBase + VGA_CRTC_DATA_OFFSET, value); 38} 39static CARD8 NVReadCrtc(vgaHWPtr pVga, CARD8 index) 40{ 41 NVPtr pNv = (NVPtr)pVga->MMIOBase; 42 VGA_WR08(pNv->PCIO, pVga->IOBase + VGA_CRTC_INDEX_OFFSET, index); 43 return (VGA_RD08(pNv->PCIO, pVga->IOBase + VGA_CRTC_DATA_OFFSET)); 44} 45static void NVWriteGr(vgaHWPtr pVga, CARD8 index, CARD8 value) 46{ 47 NVPtr pNv = (NVPtr)pVga->MMIOBase; 48 VGA_WR08(pNv->PVIO, VGA_GRAPH_INDEX, index); 49 VGA_WR08(pNv->PVIO, VGA_GRAPH_DATA, value); 50} 51static CARD8 NVReadGr(vgaHWPtr pVga, CARD8 index) 52{ 53 NVPtr pNv = (NVPtr)pVga->MMIOBase; 54 VGA_WR08(pNv->PVIO, VGA_GRAPH_INDEX, index); 55 return (VGA_RD08(pNv->PVIO, VGA_GRAPH_DATA)); 56} 57static void NVWriteSeq(vgaHWPtr pVga, CARD8 index, CARD8 value) 58{ 59 NVPtr pNv = (NVPtr)pVga->MMIOBase; 60 VGA_WR08(pNv->PVIO, VGA_SEQ_INDEX, index); 61 VGA_WR08(pNv->PVIO, VGA_SEQ_DATA, value); 62} 63static CARD8 NVReadSeq(vgaHWPtr pVga, CARD8 index) 64{ 65 NVPtr pNv = (NVPtr)pVga->MMIOBase; 66 VGA_WR08(pNv->PVIO, VGA_SEQ_INDEX, index); 67 return (VGA_RD08(pNv->PVIO, VGA_SEQ_DATA)); 68} 69static void NVWriteAttr(vgaHWPtr pVga, CARD8 index, CARD8 value) 70{ 71 NVPtr pNv = (NVPtr)pVga->MMIOBase; 72 volatile CARD8 tmp; 73 74 tmp = VGA_RD08(pNv->PCIO, pVga->IOBase + VGA_IN_STAT_1_OFFSET); 75 if (pVga->paletteEnabled) 76 index &= ~0x20; 77 else 78 index |= 0x20; 79 VGA_WR08(pNv->PCIO, VGA_ATTR_INDEX, index); 80 VGA_WR08(pNv->PCIO, VGA_ATTR_DATA_W, value); 81} 82static CARD8 NVReadAttr(vgaHWPtr pVga, CARD8 index) 83{ 84 NVPtr pNv = (NVPtr)pVga->MMIOBase; 85 volatile CARD8 tmp; 86 87 tmp = VGA_RD08(pNv->PCIO, pVga->IOBase + VGA_IN_STAT_1_OFFSET); 88 if (pVga->paletteEnabled) 89 index &= ~0x20; 90 else 91 index |= 0x20; 92 VGA_WR08(pNv->PCIO, VGA_ATTR_INDEX, index); 93 return (VGA_RD08(pNv->PCIO, VGA_ATTR_DATA_R)); 94} 95static void NVWriteMiscOut(vgaHWPtr pVga, CARD8 value) 96{ 97 NVPtr pNv = (NVPtr)pVga->MMIOBase; 98 VGA_WR08(pNv->PVIO, VGA_MISC_OUT_W, value); 99} 100static CARD8 NVReadMiscOut(vgaHWPtr pVga) 101{ 102 NVPtr pNv = (NVPtr)pVga->MMIOBase; 103 return (VGA_RD08(pNv->PVIO, VGA_MISC_OUT_R)); 104} 105static void NVEnablePalette(vgaHWPtr pVga) 106{ 107 NVPtr pNv = (NVPtr)pVga->MMIOBase; 108 volatile CARD8 tmp; 109 110 tmp = VGA_RD08(pNv->PCIO, pVga->IOBase + VGA_IN_STAT_1_OFFSET); 111 VGA_WR08(pNv->PCIO, VGA_ATTR_INDEX, 0x00); 112 pVga->paletteEnabled = TRUE; 113} 114static void NVDisablePalette(vgaHWPtr pVga) 115{ 116 NVPtr pNv = (NVPtr)pVga->MMIOBase; 117 volatile CARD8 tmp; 118 119 tmp = VGA_RD08(pNv->PCIO, pVga->IOBase + VGA_IN_STAT_1_OFFSET); 120 VGA_WR08(pNv->PCIO, VGA_ATTR_INDEX, 0x20); 121 pVga->paletteEnabled = FALSE; 122} 123static void NVWriteDacMask(vgaHWPtr pVga, CARD8 value) 124{ 125 NVPtr pNv = (NVPtr)pVga->MMIOBase; 126 VGA_WR08(pNv->PDIO, VGA_DAC_MASK, value); 127} 128static CARD8 NVReadDacMask(vgaHWPtr pVga) 129{ 130 NVPtr pNv = (NVPtr)pVga->MMIOBase; 131 return (VGA_RD08(pNv->PDIO, VGA_DAC_MASK)); 132} 133static void NVWriteDacReadAddr(vgaHWPtr pVga, CARD8 value) 134{ 135 NVPtr pNv = (NVPtr)pVga->MMIOBase; 136 VGA_WR08(pNv->PDIO, VGA_DAC_READ_ADDR, value); 137} 138static void NVWriteDacWriteAddr(vgaHWPtr pVga, CARD8 value) 139{ 140 NVPtr pNv = (NVPtr)pVga->MMIOBase; 141 VGA_WR08(pNv->PDIO, VGA_DAC_WRITE_ADDR, value); 142} 143static void NVWriteDacData(vgaHWPtr pVga, CARD8 value) 144{ 145 NVPtr pNv = (NVPtr)pVga->MMIOBase; 146 VGA_WR08(pNv->PDIO, VGA_DAC_DATA, value); 147} 148static CARD8 NVReadDacData(vgaHWPtr pVga) 149{ 150 NVPtr pNv = (NVPtr)pVga->MMIOBase; 151 return (VGA_RD08(pNv->PDIO, VGA_DAC_DATA)); 152} 153 154static Bool 155NVIsConnected (ScrnInfoPtr pScrn, int output) 156{ 157 NVPtr pNv = NVPTR(pScrn); 158 volatile U032 *PRAMDAC = pNv->PRAMDAC0; 159 CARD32 reg52C, reg608, dac0_reg608 = 0; 160 Bool present; 161 162 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 163 "Probing for analog device on output %s...\n", 164 output ? "B" : "A"); 165 166 if(output) { 167 dac0_reg608 = PRAMDAC[0x0608/4]; 168 PRAMDAC += 0x800; 169 } 170 171 reg52C = PRAMDAC[0x052C/4]; 172 reg608 = PRAMDAC[0x0608/4]; 173 174 PRAMDAC[0x0608/4] = reg608 & ~0x00010000; 175 176 PRAMDAC[0x052C/4] = reg52C & 0x0000FEEE; 177 usleep(1000); 178 PRAMDAC[0x052C/4] |= 1; 179 180 pNv->PRAMDAC0[0x0610/4] = 0x94050140; 181 pNv->PRAMDAC0[0x0608/4] |= 0x00001000; 182 183 usleep(1000); 184 185 present = (PRAMDAC[0x0608/4] & (1 << 28)) ? TRUE : FALSE; 186 187 if(present) 188 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, " ...found one\n"); 189 else 190 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, " ...can't find one\n"); 191 192 if(output) 193 pNv->PRAMDAC0[0x0608/4] = dac0_reg608; 194 195 PRAMDAC[0x052C/4] = reg52C; 196 PRAMDAC[0x0608/4] = reg608; 197 198 return present; 199} 200 201static void 202NVSelectHeadRegisters(ScrnInfoPtr pScrn, int head) 203{ 204 NVPtr pNv = NVPTR(pScrn); 205 206 if(head) { 207 pNv->PCIO = pNv->PCIO0 + 0x2000; 208 pNv->PCRTC = pNv->PCRTC0 + 0x800; 209 pNv->PRAMDAC = pNv->PRAMDAC0 + 0x800; 210 pNv->PDIO = pNv->PDIO0 + 0x2000; 211 } else { 212 pNv->PCIO = pNv->PCIO0; 213 pNv->PCRTC = pNv->PCRTC0; 214 pNv->PRAMDAC = pNv->PRAMDAC0; 215 pNv->PDIO = pNv->PDIO0; 216 } 217} 218 219static xf86MonPtr 220NVProbeDDC (ScrnInfoPtr pScrn, int bus) 221{ 222 NVPtr pNv = NVPTR(pScrn); 223 xf86MonPtr MonInfo = NULL; 224 225 if(!pNv->I2C) return NULL; 226 227 pNv->DDCBase = bus ? 0x36 : 0x3e; 228 229 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 230 "Probing for EDID on I2C bus %s...\n", bus ? "B" : "A"); 231 232#ifdef EDID_COMPLETE_RAWDATA 233 MonInfo = xf86DoEEDID(XF86_SCRN_ARG(pScrn), pNv->I2C, TRUE); 234#else 235 MonInfo = xf86DoEDID_DDC2(XF86_SCRN_ARG(pScrn), pNv->I2C); 236#endif 237 if (MonInfo) { 238 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 239 "DDC detected a %s:\n", MonInfo->features.input_type ? 240 "DFP" : "CRT"); 241 xf86PrintEDID( MonInfo ); 242 } else { 243 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 244 " ... none found\n"); 245 } 246 247 return MonInfo; 248} 249 250static void nv4GetConfig (NVPtr pNv) 251{ 252 if (pNv->PFB[0x0000/4] & 0x00000100) { 253 pNv->RamAmountKBytes = ((pNv->PFB[0x0000/4] >> 12) & 0x0F) * 1024 * 2 254 + 1024 * 2; 255 } else { 256 switch (pNv->PFB[0x0000/4] & 0x00000003) { 257 case 0: 258 pNv->RamAmountKBytes = 1024 * 32; 259 break; 260 case 1: 261 pNv->RamAmountKBytes = 1024 * 4; 262 break; 263 case 2: 264 pNv->RamAmountKBytes = 1024 * 8; 265 break; 266 case 3: 267 default: 268 pNv->RamAmountKBytes = 1024 * 16; 269 break; 270 } 271 } 272 pNv->CrystalFreqKHz = (pNv->PEXTDEV[0x0000/4] & 0x00000040) ? 14318 : 13500; 273 pNv->CURSOR = &(pNv->PRAMIN[0x1E00]); 274 pNv->MinVClockFreqKHz = 12000; 275 pNv->MaxVClockFreqKHz = 350000; 276} 277 278static void nv10GetConfig (NVPtr pNv) 279{ 280 CARD32 implementation = pNv->Chipset & 0x0ff0; 281 282#if X_BYTE_ORDER == X_BIG_ENDIAN 283 /* turn on big endian register access */ 284 if(!(pNv->PMC[0x0004/4] & 0x01000001)) { 285 pNv->PMC[0x0004/4] = 0x01000001; 286 mem_barrier(); 287 } 288#endif 289 290#if XSERVER_LIBPCIACCESS 291 { 292 /* [AGP]: I don't know if this is correct */ 293 struct pci_device *dev = pci_device_find_by_slot(0, 0, 0, 1); 294 295 if(implementation == 0x01a0) { 296 uint32_t amt; 297 pci_device_cfg_read_u32(dev, &amt, 0x7C); 298 pNv->RamAmountKBytes = (((amt >> 6) & 31) + 1) * 1024; 299 } else if(implementation == 0x01f0) { 300 uint32_t amt; 301 pci_device_cfg_read_u32(dev, &amt, 0x84); 302 pNv->RamAmountKBytes = (((amt >> 4) & 127) + 1) * 1024; 303 } else { 304 pNv->RamAmountKBytes = (pNv->PFB[0x020C/4] & 0xFFF00000) >> 10; 305 } 306 } 307#else 308 if(implementation == 0x01a0) { 309 int amt = pciReadLong(pciTag(0, 0, 1), 0x7C); 310 pNv->RamAmountKBytes = (((amt >> 6) & 31) + 1) * 1024; 311 } else if(implementation == 0x01f0) { 312 int amt = pciReadLong(pciTag(0, 0, 1), 0x84); 313 pNv->RamAmountKBytes = (((amt >> 4) & 127) + 1) * 1024; 314 } else { 315 pNv->RamAmountKBytes = (pNv->PFB[0x020C/4] & 0xFFF00000) >> 10; 316 } 317#endif 318 319 if(pNv->RamAmountKBytes > 256*1024) 320 pNv->RamAmountKBytes = 256*1024; 321 322 pNv->CrystalFreqKHz = (pNv->PEXTDEV[0x0000/4] & (1 << 6)) ? 14318 : 13500; 323 324 if(pNv->twoHeads && (implementation != 0x0110)) 325 { 326 if(pNv->PEXTDEV[0x0000/4] & (1 << 22)) 327 pNv->CrystalFreqKHz = 27000; 328 } 329 330 pNv->CURSOR = NULL; /* can't set this here */ 331 pNv->MinVClockFreqKHz = 12000; 332 pNv->MaxVClockFreqKHz = pNv->twoStagePLL ? 400000 : 350000; 333} 334 335 336void 337NVCommonSetup(ScrnInfoPtr pScrn) 338{ 339 NVPtr pNv = NVPTR(pScrn); 340 vgaHWPtr pVga = VGAHWPTR(pScrn); 341 CARD16 implementation = pNv->Chipset & 0x0ff0; 342 xf86MonPtr monitorA, monitorB; 343 Bool mobile = FALSE; 344 Bool tvA = FALSE; 345 Bool tvB = FALSE; 346 int FlatPanel = -1; /* really means the CRTC is slaved */ 347 Bool Television = FALSE; 348 void *tmp; 349#if XSERVER_LIBPCIACCESS 350 int err; 351#endif 352 353 /* 354 * Override VGA I/O routines. 355 */ 356 pVga->writeCrtc = NVWriteCrtc; 357 pVga->readCrtc = NVReadCrtc; 358 pVga->writeGr = NVWriteGr; 359 pVga->readGr = NVReadGr; 360 pVga->writeAttr = NVWriteAttr; 361 pVga->readAttr = NVReadAttr; 362 pVga->writeSeq = NVWriteSeq; 363 pVga->readSeq = NVReadSeq; 364 pVga->writeMiscOut = NVWriteMiscOut; 365 pVga->readMiscOut = NVReadMiscOut; 366 pVga->enablePalette = NVEnablePalette; 367 pVga->disablePalette = NVDisablePalette; 368 pVga->writeDacMask = NVWriteDacMask; 369 pVga->readDacMask = NVReadDacMask; 370 pVga->writeDacWriteAddr = NVWriteDacWriteAddr; 371 pVga->writeDacReadAddr = NVWriteDacReadAddr; 372 pVga->writeDacData = NVWriteDacData; 373 pVga->readDacData = NVReadDacData; 374 /* 375 * Note: There are different pointers to the CRTC/AR and GR/SEQ registers. 376 * Bastardize the intended uses of these to make it work. 377 */ 378 pVga->MMIOBase = (CARD8 *)pNv; 379 pVga->MMIOOffset = 0; 380 381#if XSERVER_LIBPCIACCESS 382 err = pci_device_map_range(pNv->PciInfo, pNv->IOAddress, 0x01000000, 383 PCI_DEV_MAP_FLAG_WRITABLE, &tmp); 384 if (err != 0) { 385 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 386 "pci_device_map_range failed: %s\n", strerror(err)); 387 } 388#else 389 tmp = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO | VIDMEM_READSIDEEFFECT, 390 pNv->PciTag, pNv->IOAddress, 0x01000000); 391#endif 392 pNv->REGS = tmp; 393 394 pNv->PRAMIN = pNv->REGS + (0x00710000/4); 395 pNv->PCRTC0 = pNv->REGS + (0x00600000/4); 396 pNv->PRAMDAC0 = pNv->REGS + (0x00680000/4); 397 pNv->PFB = pNv->REGS + (0x00100000/4); 398 pNv->PFIFO = pNv->REGS + (0x00002000/4); 399 pNv->PGRAPH = pNv->REGS + (0x00400000/4); 400 pNv->PEXTDEV = pNv->REGS + (0x00101000/4); 401 pNv->PTIMER = pNv->REGS + (0x00009000/4); 402 pNv->PMC = pNv->REGS + (0x00000000/4); 403 pNv->FIFO = pNv->REGS + (0x00800000/4); 404 405 /* 8 bit registers */ 406 pNv->PCIO0 = (U008*)pNv->REGS + 0x00601000; 407 pNv->PDIO0 = (U008*)pNv->REGS + 0x00681000; 408 pNv->PVIO = (U008*)pNv->REGS + 0x000C0000; 409 410 pNv->twoHeads = (pNv->Architecture >= NV_ARCH_10) && 411 (implementation != 0x0100) && 412 (implementation != 0x0150) && 413 (implementation != 0x01A0) && 414 (implementation != 0x0200); 415 416 pNv->fpScaler = (pNv->FpScale && pNv->twoHeads && (implementation!=0x0110)); 417 418 pNv->twoStagePLL = (implementation == 0x0310) || 419 (implementation == 0x0340) || 420 (pNv->Architecture >= NV_ARCH_40); 421 422 pNv->WaitVSyncPossible = (pNv->Architecture >= NV_ARCH_10) && 423 (implementation != 0x0100); 424 425 pNv->BlendingPossible = ((pNv->Chipset & 0xffff) != 0x0020); 426 427 /* look for known laptop chips */ 428 switch(pNv->Chipset & 0xffff) { 429 case 0x0112: 430 case 0x0174: 431 case 0x0175: 432 case 0x0176: 433 case 0x0177: 434 case 0x0179: 435 case 0x017C: 436 case 0x017D: 437 case 0x0186: 438 case 0x0187: 439 case 0x018D: 440 case 0x0228: 441 case 0x0286: 442 case 0x028C: 443 case 0x0316: 444 case 0x0317: 445 case 0x031A: 446 case 0x031B: 447 case 0x031C: 448 case 0x031D: 449 case 0x031E: 450 case 0x031F: 451 case 0x0324: 452 case 0x0325: 453 case 0x0328: 454 case 0x0329: 455 case 0x032C: 456 case 0x032D: 457 case 0x0347: 458 case 0x0348: 459 case 0x0349: 460 case 0x034B: 461 case 0x034C: 462 case 0x0160: 463 case 0x0166: 464 case 0x0169: 465 case 0x016B: 466 case 0x016C: 467 case 0x016D: 468 case 0x00C8: 469 case 0x00CC: 470 case 0x0144: 471 case 0x0146: 472 case 0x0148: 473 case 0x0098: 474 case 0x0099: 475 mobile = TRUE; 476 break; 477 default: 478 break; 479 } 480 481 if(pNv->Architecture == NV_ARCH_04) 482 nv4GetConfig(pNv); 483 else 484 nv10GetConfig(pNv); 485 486 NVSelectHeadRegisters(pScrn, 0); 487 488 NVLockUnlock(pNv, 0); 489 490 NVI2CInit(pScrn); 491 492 pNv->Television = FALSE; 493 494 vgaHWGetIOBase(pVga); 495 496 if(!pNv->twoHeads) { 497 pNv->CRTCnumber = 0; 498 if((monitorA = NVProbeDDC(pScrn, 0))) { 499 FlatPanel = monitorA->features.input_type ? 1 : 0; 500 501 /* NV4 doesn't support FlatPanels */ 502 if((pNv->Chipset & 0x0fff) <= 0x0020) 503 FlatPanel = 0; 504 } else { 505 VGA_WR08(pNv->PCIO, 0x03D4, 0x28); 506 if(VGA_RD08(pNv->PCIO, 0x03D5) & 0x80) { 507 VGA_WR08(pNv->PCIO, 0x03D4, 0x33); 508 if(!(VGA_RD08(pNv->PCIO, 0x03D5) & 0x01)) 509 Television = TRUE; 510 FlatPanel = 1; 511 } else { 512 FlatPanel = 0; 513 } 514 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 515 "HW is currently programmed for %s\n", 516 FlatPanel ? (Television ? "TV" : "DFP") : "CRT"); 517 } 518 519 if(pNv->FlatPanel == -1) { 520 pNv->FlatPanel = FlatPanel; 521 pNv->Television = Television; 522 } else { 523 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 524 "Forcing display type to %s as specified\n", 525 pNv->FlatPanel ? "DFP" : "CRT"); 526 } 527 } else { 528 CARD8 outputAfromCRTC, outputBfromCRTC; 529 int CRTCnumber = -1; 530 CARD8 slaved_on_A, slaved_on_B; 531 Bool analog_on_A, analog_on_B; 532 CARD32 oldhead; 533 CARD8 cr44; 534 535 if(implementation != 0x0110) { 536 if(pNv->PRAMDAC0[0x0000052C/4] & 0x100) 537 outputAfromCRTC = 1; 538 else 539 outputAfromCRTC = 0; 540 if(pNv->PRAMDAC0[0x0000252C/4] & 0x100) 541 outputBfromCRTC = 1; 542 else 543 outputBfromCRTC = 0; 544 analog_on_A = NVIsConnected(pScrn, 0); 545 analog_on_B = NVIsConnected(pScrn, 1); 546 } else { 547 outputAfromCRTC = 0; 548 outputBfromCRTC = 1; 549 analog_on_A = FALSE; 550 analog_on_B = FALSE; 551 } 552 553 VGA_WR08(pNv->PCIO, 0x03D4, 0x44); 554 cr44 = VGA_RD08(pNv->PCIO, 0x03D5); 555 556 VGA_WR08(pNv->PCIO, 0x03D5, 3); 557 NVSelectHeadRegisters(pScrn, 1); 558 NVLockUnlock(pNv, 0); 559 560 VGA_WR08(pNv->PCIO, 0x03D4, 0x28); 561 slaved_on_B = VGA_RD08(pNv->PCIO, 0x03D5) & 0x80; 562 if(slaved_on_B) { 563 VGA_WR08(pNv->PCIO, 0x03D4, 0x33); 564 tvB = !(VGA_RD08(pNv->PCIO, 0x03D5) & 0x01); 565 } 566 567 VGA_WR08(pNv->PCIO, 0x03D4, 0x44); 568 VGA_WR08(pNv->PCIO, 0x03D5, 0); 569 NVSelectHeadRegisters(pScrn, 0); 570 NVLockUnlock(pNv, 0); 571 572 VGA_WR08(pNv->PCIO, 0x03D4, 0x28); 573 slaved_on_A = VGA_RD08(pNv->PCIO, 0x03D5) & 0x80; 574 if(slaved_on_A) { 575 VGA_WR08(pNv->PCIO, 0x03D4, 0x33); 576 tvA = !(VGA_RD08(pNv->PCIO, 0x03D5) & 0x01); 577 } 578 579 oldhead = pNv->PCRTC0[0x00000860/4]; 580 pNv->PCRTC0[0x00000860/4] = oldhead | 0x00000010; 581 582 monitorA = NVProbeDDC(pScrn, 0); 583 monitorB = NVProbeDDC(pScrn, 1); 584 585 if(slaved_on_A && !tvA) { 586 CRTCnumber = 0; 587 FlatPanel = 1; 588 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 589 "CRTC 0 is currently programmed for DFP\n"); 590 } else 591 if(slaved_on_B && !tvB) { 592 CRTCnumber = 1; 593 FlatPanel = 1; 594 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 595 "CRTC 1 is currently programmed for DFP\n"); 596 } else 597 if(analog_on_A) { 598 CRTCnumber = outputAfromCRTC; 599 FlatPanel = 0; 600 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 601 "CRTC %i appears to have a CRT attached\n", CRTCnumber); 602 } else 603 if(analog_on_B) { 604 CRTCnumber = outputBfromCRTC; 605 FlatPanel = 0; 606 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 607 "CRTC %i appears to have a CRT attached\n", CRTCnumber); 608 } else 609 if(slaved_on_A) { 610 CRTCnumber = 0; 611 FlatPanel = 1; 612 Television = 1; 613 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 614 "CRTC 0 is currently programmed for TV\n"); 615 } else 616 if(slaved_on_B) { 617 CRTCnumber = 1; 618 FlatPanel = 1; 619 Television = 1; 620 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 621 "CRTC 1 is currently programmed for TV\n"); 622 } else 623 if(monitorA) { 624 FlatPanel = monitorA->features.input_type ? 1 : 0; 625 } else 626 if(monitorB) { 627 FlatPanel = monitorB->features.input_type ? 1 : 0; 628 } 629 630 if(pNv->FlatPanel == -1) { 631 if(FlatPanel != -1) { 632 pNv->FlatPanel = FlatPanel; 633 pNv->Television = Television; 634 } else { 635 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 636 "Unable to detect display type...\n"); 637 if(mobile) { 638 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, 639 "...On a laptop, assuming DFP\n"); 640 pNv->FlatPanel = 1; 641 } else { 642 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, 643 "...Using default of CRT\n"); 644 pNv->FlatPanel = 0; 645 } 646 } 647 } else { 648 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 649 "Forcing display type to %s as specified\n", 650 pNv->FlatPanel ? "DFP" : "CRT"); 651 } 652 653 if(pNv->CRTCnumber == -1) { 654 if(CRTCnumber != -1) pNv->CRTCnumber = CRTCnumber; 655 else { 656 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 657 "Unable to detect which CRTCNumber...\n"); 658 if(pNv->FlatPanel) pNv->CRTCnumber = 1; 659 else pNv->CRTCnumber = 0; 660 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, 661 "...Defaulting to CRTCNumber %i\n", pNv->CRTCnumber); 662 } 663 } else { 664 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 665 "Forcing CRTCNumber %i as specified\n", pNv->CRTCnumber); 666 } 667 668 if(monitorA) { 669 if((monitorA->features.input_type && pNv->FlatPanel) || 670 (!monitorA->features.input_type && !pNv->FlatPanel)) 671 { 672 if(monitorB) { 673 free(monitorB); 674 monitorB = NULL; 675 } 676 } else { 677 free(monitorA); 678 monitorA = NULL; 679 } 680 } 681 682 if(monitorB) { 683 if((monitorB->features.input_type && !pNv->FlatPanel) || 684 (!monitorB->features.input_type && pNv->FlatPanel)) 685 { 686 free(monitorB); 687 } else { 688 monitorA = monitorB; 689 } 690 monitorB = NULL; 691 } 692 693 if(implementation == 0x0110) 694 cr44 = pNv->CRTCnumber * 0x3; 695 696 pNv->PCRTC0[0x00000860/4] = oldhead; 697 698 VGA_WR08(pNv->PCIO, 0x03D4, 0x44); 699 VGA_WR08(pNv->PCIO, 0x03D5, cr44); 700 NVSelectHeadRegisters(pScrn, pNv->CRTCnumber); 701 } 702 703 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 704 "Using %s on CRTC %i\n", 705 pNv->FlatPanel ? (pNv->Television ? "TV" : "DFP") : "CRT", 706 pNv->CRTCnumber); 707 708 if(pNv->FlatPanel && !pNv->Television) { 709 pNv->fpWidth = pNv->PRAMDAC[0x0820/4] + 1; 710 pNv->fpHeight = pNv->PRAMDAC[0x0800/4] + 1; 711 pNv->fpVTotal = pNv->PRAMDAC[0x804/4] + 1; 712 pNv->fpSyncs = pNv->PRAMDAC[0x0848/4] & 0x30000033; 713 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Panel size is %i x %i\n", 714 pNv->fpWidth, pNv->fpHeight); 715 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NOTE: This driver cannot " 716 "reconfigure the BIOS-programmed size.\n"); 717 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "These dimensions will be used as " 718 "the panel size for mode validation.\n"); 719 } 720 721 if(monitorA) 722 xf86SetDDCproperties(pScrn, monitorA); 723 724 if(!pNv->FlatPanel || (pScrn->depth != 24) || !pNv->twoHeads) 725 pNv->FPDither = FALSE; 726 727 pNv->LVDS = FALSE; 728 if(pNv->FlatPanel && pNv->twoHeads) { 729 pNv->PRAMDAC0[0x08B0/4] = 0x00010004; 730 if(pNv->PRAMDAC0[0x08B4/4] & 1) 731 pNv->LVDS = TRUE; 732 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel is %s\n", 733 pNv->LVDS ? "LVDS" : "TMDS"); 734 } 735} 736