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