1 /***************************************************************************\ 2|* *| 3|* Copyright 2003 NVIDIA, Corporation. All rights reserved. *| 4|* *| 5|* NOTICE TO USER: The source code is copyrighted under U.S. and *| 6|* international laws. Users and possessors of this source code are *| 7|* hereby granted a nonexclusive, royalty-free copyright license to *| 8|* use this code in individual and commercial software. *| 9|* *| 10|* Any use of this source code must include, in the user documenta- *| 11|* tion and internal comments to the code, notices to the end user *| 12|* as follows: *| 13|* *| 14|* Copyright 2003 NVIDIA, Corporation. All rights reserved. *| 15|* *| 16|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *| 17|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *| 18|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *| 19|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *| 20|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *| 21|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *| 22|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *| 23|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *| 24|* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *| 25|* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *| 26|* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *| 27|* *| 28|* U.S. Government End Users. This source code is a "commercial *| 29|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *| 30|* consisting of "commercial computer software" and "commercial *| 31|* computer software documentation," as such terms are used in *| 32|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *| 33|* ment only as a commercial end item. Consistent with 48 C.F.R. *| 34|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *| 35|* all U.S. Government End Users acquire the source code with only *| 36|* those rights set forth herein. *| 37|* *| 38 \***************************************************************************/ 39 40/* 41 * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/ 42 * XFree86 'nv' driver, this source code is provided under MIT-style licensing 43 * where the source code is provided "as is" without warranty of any kind. 44 * The only usage restriction is for the copyright notices to be retained 45 * whenever code is used. 46 * 47 * Antonino Daplas <adaplas@pol.net> 2005-03-11 48 */ 49 50#include <video/vga.h> 51#include <linux/delay.h> 52#include <linux/pci.h> 53#include <linux/slab.h> 54#include "nv_type.h" 55#include "nv_local.h" 56#include "nv_proto.h" 57/* 58 * Override VGA I/O routines. 59 */ 60void NVWriteCrtc(struct nvidia_par *par, u8 index, u8 value) 61{ 62 VGA_WR08(par->PCIO, par->IOBase + 0x04, index); 63 VGA_WR08(par->PCIO, par->IOBase + 0x05, value); 64} 65u8 NVReadCrtc(struct nvidia_par *par, u8 index) 66{ 67 VGA_WR08(par->PCIO, par->IOBase + 0x04, index); 68 return (VGA_RD08(par->PCIO, par->IOBase + 0x05)); 69} 70void NVWriteGr(struct nvidia_par *par, u8 index, u8 value) 71{ 72 VGA_WR08(par->PVIO, VGA_GFX_I, index); 73 VGA_WR08(par->PVIO, VGA_GFX_D, value); 74} 75u8 NVReadGr(struct nvidia_par *par, u8 index) 76{ 77 VGA_WR08(par->PVIO, VGA_GFX_I, index); 78 return (VGA_RD08(par->PVIO, VGA_GFX_D)); 79} 80void NVWriteSeq(struct nvidia_par *par, u8 index, u8 value) 81{ 82 VGA_WR08(par->PVIO, VGA_SEQ_I, index); 83 VGA_WR08(par->PVIO, VGA_SEQ_D, value); 84} 85u8 NVReadSeq(struct nvidia_par *par, u8 index) 86{ 87 VGA_WR08(par->PVIO, VGA_SEQ_I, index); 88 return (VGA_RD08(par->PVIO, VGA_SEQ_D)); 89} 90void NVWriteAttr(struct nvidia_par *par, u8 index, u8 value) 91{ 92 volatile u8 tmp; 93 94 tmp = VGA_RD08(par->PCIO, par->IOBase + 0x0a); 95 if (par->paletteEnabled) 96 index &= ~0x20; 97 else 98 index |= 0x20; 99 VGA_WR08(par->PCIO, VGA_ATT_IW, index); 100 VGA_WR08(par->PCIO, VGA_ATT_W, value); 101} 102u8 NVReadAttr(struct nvidia_par *par, u8 index) 103{ 104 volatile u8 tmp; 105 106 tmp = VGA_RD08(par->PCIO, par->IOBase + 0x0a); 107 if (par->paletteEnabled) 108 index &= ~0x20; 109 else 110 index |= 0x20; 111 VGA_WR08(par->PCIO, VGA_ATT_IW, index); 112 return (VGA_RD08(par->PCIO, VGA_ATT_R)); 113} 114void NVWriteMiscOut(struct nvidia_par *par, u8 value) 115{ 116 VGA_WR08(par->PVIO, VGA_MIS_W, value); 117} 118u8 NVReadMiscOut(struct nvidia_par *par) 119{ 120 return (VGA_RD08(par->PVIO, VGA_MIS_R)); 121} 122#if 0 123void NVEnablePalette(struct nvidia_par *par) 124{ 125 volatile u8 tmp; 126 127 tmp = VGA_RD08(par->PCIO, par->IOBase + 0x0a); 128 VGA_WR08(par->PCIO, VGA_ATT_IW, 0x00); 129 par->paletteEnabled = 1; 130} 131void NVDisablePalette(struct nvidia_par *par) 132{ 133 volatile u8 tmp; 134 135 tmp = VGA_RD08(par->PCIO, par->IOBase + 0x0a); 136 VGA_WR08(par->PCIO, VGA_ATT_IW, 0x20); 137 par->paletteEnabled = 0; 138} 139#endif /* 0 */ 140void NVWriteDacMask(struct nvidia_par *par, u8 value) 141{ 142 VGA_WR08(par->PDIO, VGA_PEL_MSK, value); 143} 144#if 0 145u8 NVReadDacMask(struct nvidia_par *par) 146{ 147 return (VGA_RD08(par->PDIO, VGA_PEL_MSK)); 148} 149#endif /* 0 */ 150void NVWriteDacReadAddr(struct nvidia_par *par, u8 value) 151{ 152 VGA_WR08(par->PDIO, VGA_PEL_IR, value); 153} 154void NVWriteDacWriteAddr(struct nvidia_par *par, u8 value) 155{ 156 VGA_WR08(par->PDIO, VGA_PEL_IW, value); 157} 158void NVWriteDacData(struct nvidia_par *par, u8 value) 159{ 160 VGA_WR08(par->PDIO, VGA_PEL_D, value); 161} 162u8 NVReadDacData(struct nvidia_par *par) 163{ 164 return (VGA_RD08(par->PDIO, VGA_PEL_D)); 165} 166 167static int NVIsConnected(struct nvidia_par *par, int output) 168{ 169 volatile u32 __iomem *PRAMDAC = par->PRAMDAC0; 170 u32 reg52C, reg608, dac0_reg608 = 0; 171 int present; 172 173 if (output) { 174 dac0_reg608 = NV_RD32(PRAMDAC, 0x0608); 175 PRAMDAC += 0x800; 176 } 177 178 reg52C = NV_RD32(PRAMDAC, 0x052C); 179 reg608 = NV_RD32(PRAMDAC, 0x0608); 180 181 NV_WR32(PRAMDAC, 0x0608, reg608 & ~0x00010000); 182 183 NV_WR32(PRAMDAC, 0x052C, reg52C & 0x0000FEEE); 184 msleep(1); 185 NV_WR32(PRAMDAC, 0x052C, NV_RD32(PRAMDAC, 0x052C) | 1); 186 187 NV_WR32(par->PRAMDAC0, 0x0610, 0x94050140); 188 NV_WR32(par->PRAMDAC0, 0x0608, NV_RD32(par->PRAMDAC0, 0x0608) | 189 0x00001000); 190 191 msleep(1); 192 193 present = (NV_RD32(PRAMDAC, 0x0608) & (1 << 28)) ? 1 : 0; 194 195 if (present) 196 printk("nvidiafb: CRTC%i analog found\n", output); 197 else 198 printk("nvidiafb: CRTC%i analog not found\n", output); 199 200 if (output) 201 NV_WR32(par->PRAMDAC0, 0x0608, dac0_reg608); 202 203 NV_WR32(PRAMDAC, 0x052C, reg52C); 204 NV_WR32(PRAMDAC, 0x0608, reg608); 205 206 return present; 207} 208 209static void NVSelectHeadRegisters(struct nvidia_par *par, int head) 210{ 211 if (head) { 212 par->PCIO = par->PCIO0 + 0x2000; 213 par->PCRTC = par->PCRTC0 + 0x800; 214 par->PRAMDAC = par->PRAMDAC0 + 0x800; 215 par->PDIO = par->PDIO0 + 0x2000; 216 } else { 217 par->PCIO = par->PCIO0; 218 par->PCRTC = par->PCRTC0; 219 par->PRAMDAC = par->PRAMDAC0; 220 par->PDIO = par->PDIO0; 221 } 222} 223 224static void nv4GetConfig(struct nvidia_par *par) 225{ 226 if (NV_RD32(par->PFB, 0x0000) & 0x00000100) { 227 par->RamAmountKBytes = 228 ((NV_RD32(par->PFB, 0x0000) >> 12) & 0x0F) * 1024 * 2 + 229 1024 * 2; 230 } else { 231 switch (NV_RD32(par->PFB, 0x0000) & 0x00000003) { 232 case 0: 233 par->RamAmountKBytes = 1024 * 32; 234 break; 235 case 1: 236 par->RamAmountKBytes = 1024 * 4; 237 break; 238 case 2: 239 par->RamAmountKBytes = 1024 * 8; 240 break; 241 case 3: 242 default: 243 par->RamAmountKBytes = 1024 * 16; 244 break; 245 } 246 } 247 par->CrystalFreqKHz = (NV_RD32(par->PEXTDEV, 0x0000) & 0x00000040) ? 248 14318 : 13500; 249 par->CURSOR = &par->PRAMIN[0x1E00]; 250 par->MinVClockFreqKHz = 12000; 251 par->MaxVClockFreqKHz = 350000; 252} 253 254static void nv10GetConfig(struct nvidia_par *par) 255{ 256 struct pci_dev *dev; 257 u32 implementation = par->Chipset & 0x0ff0; 258 259#ifdef __BIG_ENDIAN 260 /* turn on big endian register access */ 261 if (!(NV_RD32(par->PMC, 0x0004) & 0x01000001)) { 262 NV_WR32(par->PMC, 0x0004, 0x01000001); 263 mb(); 264 } 265#endif 266 267 dev = pci_get_bus_and_slot(0, 1); 268 if ((par->Chipset & 0xffff) == 0x01a0) { 269 u32 amt; 270 271 pci_read_config_dword(dev, 0x7c, &amt); 272 par->RamAmountKBytes = (((amt >> 6) & 31) + 1) * 1024; 273 } else if ((par->Chipset & 0xffff) == 0x01f0) { 274 u32 amt; 275 276 pci_read_config_dword(dev, 0x84, &amt); 277 par->RamAmountKBytes = (((amt >> 4) & 127) + 1) * 1024; 278 } else { 279 par->RamAmountKBytes = 280 (NV_RD32(par->PFB, 0x020C) & 0xFFF00000) >> 10; 281 } 282 pci_dev_put(dev); 283 284 par->CrystalFreqKHz = (NV_RD32(par->PEXTDEV, 0x0000) & (1 << 6)) ? 285 14318 : 13500; 286 287 if (par->twoHeads && (implementation != 0x0110)) { 288 if (NV_RD32(par->PEXTDEV, 0x0000) & (1 << 22)) 289 par->CrystalFreqKHz = 27000; 290 } 291 292 par->CURSOR = NULL; /* can't set this here */ 293 par->MinVClockFreqKHz = 12000; 294 par->MaxVClockFreqKHz = par->twoStagePLL ? 400000 : 350000; 295} 296 297int NVCommonSetup(struct fb_info *info) 298{ 299 struct nvidia_par *par = info->par; 300 struct fb_var_screeninfo *var; 301 u16 implementation = par->Chipset & 0x0ff0; 302 u8 *edidA = NULL, *edidB = NULL; 303 struct fb_monspecs *monitorA, *monitorB; 304 struct fb_monspecs *monA = NULL, *monB = NULL; 305 int mobile = 0; 306 int tvA = 0; 307 int tvB = 0; 308 int FlatPanel = -1; /* really means the CRTC is slaved */ 309 int Television = 0; 310 int err = 0; 311 312 var = kzalloc(sizeof(struct fb_var_screeninfo), GFP_KERNEL); 313 monitorA = kzalloc(sizeof(struct fb_monspecs), GFP_KERNEL); 314 monitorB = kzalloc(sizeof(struct fb_monspecs), GFP_KERNEL); 315 316 if (!var || !monitorA || !monitorB) { 317 err = -ENOMEM; 318 goto done; 319 } 320 321 par->PRAMIN = par->REGS + (0x00710000 / 4); 322 par->PCRTC0 = par->REGS + (0x00600000 / 4); 323 par->PRAMDAC0 = par->REGS + (0x00680000 / 4); 324 par->PFB = par->REGS + (0x00100000 / 4); 325 par->PFIFO = par->REGS + (0x00002000 / 4); 326 par->PGRAPH = par->REGS + (0x00400000 / 4); 327 par->PEXTDEV = par->REGS + (0x00101000 / 4); 328 par->PTIMER = par->REGS + (0x00009000 / 4); 329 par->PMC = par->REGS + (0x00000000 / 4); 330 par->FIFO = par->REGS + (0x00800000 / 4); 331 332 /* 8 bit registers */ 333 par->PCIO0 = (u8 __iomem *) par->REGS + 0x00601000; 334 par->PDIO0 = (u8 __iomem *) par->REGS + 0x00681000; 335 par->PVIO = (u8 __iomem *) par->REGS + 0x000C0000; 336 337 par->twoHeads = (par->Architecture >= NV_ARCH_10) && 338 (implementation != 0x0100) && 339 (implementation != 0x0150) && 340 (implementation != 0x01A0) && (implementation != 0x0200); 341 342 par->fpScaler = (par->FpScale && par->twoHeads && 343 (implementation != 0x0110)); 344 345 par->twoStagePLL = (implementation == 0x0310) || 346 (implementation == 0x0340) || (par->Architecture >= NV_ARCH_40); 347 348 par->WaitVSyncPossible = (par->Architecture >= NV_ARCH_10) && 349 (implementation != 0x0100); 350 351 par->BlendingPossible = ((par->Chipset & 0xffff) != 0x0020); 352 353 /* look for known laptop chips */ 354 switch (par->Chipset & 0xffff) { 355 case 0x0112: 356 case 0x0174: 357 case 0x0175: 358 case 0x0176: 359 case 0x0177: 360 case 0x0179: 361 case 0x017C: 362 case 0x017D: 363 case 0x0186: 364 case 0x0187: 365 case 0x018D: 366 case 0x01D7: 367 case 0x0228: 368 case 0x0286: 369 case 0x028C: 370 case 0x0316: 371 case 0x0317: 372 case 0x031A: 373 case 0x031B: 374 case 0x031C: 375 case 0x031D: 376 case 0x031E: 377 case 0x031F: 378 case 0x0324: 379 case 0x0325: 380 case 0x0328: 381 case 0x0329: 382 case 0x032C: 383 case 0x032D: 384 case 0x0347: 385 case 0x0348: 386 case 0x0349: 387 case 0x034B: 388 case 0x034C: 389 case 0x0160: 390 case 0x0166: 391 case 0x0169: 392 case 0x016B: 393 case 0x016C: 394 case 0x016D: 395 case 0x00C8: 396 case 0x00CC: 397 case 0x0144: 398 case 0x0146: 399 case 0x0147: 400 case 0x0148: 401 case 0x0098: 402 case 0x0099: 403 mobile = 1; 404 break; 405 default: 406 break; 407 } 408 409 if (par->Architecture == NV_ARCH_04) 410 nv4GetConfig(par); 411 else 412 nv10GetConfig(par); 413 414 NVSelectHeadRegisters(par, 0); 415 416 NVLockUnlock(par, 0); 417 418 par->IOBase = (NVReadMiscOut(par) & 0x01) ? 0x3d0 : 0x3b0; 419 420 par->Television = 0; 421 422 nvidia_create_i2c_busses(par); 423 if (!par->twoHeads) { 424 par->CRTCnumber = 0; 425 if (nvidia_probe_i2c_connector(info, 1, &edidA)) 426 nvidia_probe_of_connector(info, 1, &edidA); 427 if (edidA && !fb_parse_edid(edidA, var)) { 428 printk("nvidiafb: EDID found from BUS1\n"); 429 monA = monitorA; 430 fb_edid_to_monspecs(edidA, monA); 431 FlatPanel = (monA->input & FB_DISP_DDI) ? 1 : 0; 432 433 /* NV4 doesn't support FlatPanels */ 434 if ((par->Chipset & 0x0fff) <= 0x0020) 435 FlatPanel = 0; 436 } else { 437 VGA_WR08(par->PCIO, 0x03D4, 0x28); 438 if (VGA_RD08(par->PCIO, 0x03D5) & 0x80) { 439 VGA_WR08(par->PCIO, 0x03D4, 0x33); 440 if (!(VGA_RD08(par->PCIO, 0x03D5) & 0x01)) 441 Television = 1; 442 FlatPanel = 1; 443 } else { 444 FlatPanel = 0; 445 } 446 printk("nvidiafb: HW is currently programmed for %s\n", 447 FlatPanel ? (Television ? "TV" : "DFP") : 448 "CRT"); 449 } 450 451 if (par->FlatPanel == -1) { 452 par->FlatPanel = FlatPanel; 453 par->Television = Television; 454 } else { 455 printk("nvidiafb: Forcing display type to %s as " 456 "specified\n", par->FlatPanel ? "DFP" : "CRT"); 457 } 458 } else { 459 u8 outputAfromCRTC, outputBfromCRTC; 460 int CRTCnumber = -1; 461 u8 slaved_on_A, slaved_on_B; 462 int analog_on_A, analog_on_B; 463 u32 oldhead; 464 u8 cr44; 465 466 if (implementation != 0x0110) { 467 if (NV_RD32(par->PRAMDAC0, 0x0000052C) & 0x100) 468 outputAfromCRTC = 1; 469 else 470 outputAfromCRTC = 0; 471 if (NV_RD32(par->PRAMDAC0, 0x0000252C) & 0x100) 472 outputBfromCRTC = 1; 473 else 474 outputBfromCRTC = 0; 475 analog_on_A = NVIsConnected(par, 0); 476 analog_on_B = NVIsConnected(par, 1); 477 } else { 478 outputAfromCRTC = 0; 479 outputBfromCRTC = 1; 480 analog_on_A = 0; 481 analog_on_B = 0; 482 } 483 484 VGA_WR08(par->PCIO, 0x03D4, 0x44); 485 cr44 = VGA_RD08(par->PCIO, 0x03D5); 486 487 VGA_WR08(par->PCIO, 0x03D5, 3); 488 NVSelectHeadRegisters(par, 1); 489 NVLockUnlock(par, 0); 490 491 VGA_WR08(par->PCIO, 0x03D4, 0x28); 492 slaved_on_B = VGA_RD08(par->PCIO, 0x03D5) & 0x80; 493 if (slaved_on_B) { 494 VGA_WR08(par->PCIO, 0x03D4, 0x33); 495 tvB = !(VGA_RD08(par->PCIO, 0x03D5) & 0x01); 496 } 497 498 VGA_WR08(par->PCIO, 0x03D4, 0x44); 499 VGA_WR08(par->PCIO, 0x03D5, 0); 500 NVSelectHeadRegisters(par, 0); 501 NVLockUnlock(par, 0); 502 503 VGA_WR08(par->PCIO, 0x03D4, 0x28); 504 slaved_on_A = VGA_RD08(par->PCIO, 0x03D5) & 0x80; 505 if (slaved_on_A) { 506 VGA_WR08(par->PCIO, 0x03D4, 0x33); 507 tvA = !(VGA_RD08(par->PCIO, 0x03D5) & 0x01); 508 } 509 510 oldhead = NV_RD32(par->PCRTC0, 0x00000860); 511 NV_WR32(par->PCRTC0, 0x00000860, oldhead | 0x00000010); 512 513 if (nvidia_probe_i2c_connector(info, 1, &edidA)) 514 nvidia_probe_of_connector(info, 1, &edidA); 515 if (edidA && !fb_parse_edid(edidA, var)) { 516 printk("nvidiafb: EDID found from BUS1\n"); 517 monA = monitorA; 518 fb_edid_to_monspecs(edidA, monA); 519 } 520 521 if (nvidia_probe_i2c_connector(info, 2, &edidB)) 522 nvidia_probe_of_connector(info, 2, &edidB); 523 if (edidB && !fb_parse_edid(edidB, var)) { 524 printk("nvidiafb: EDID found from BUS2\n"); 525 monB = monitorB; 526 fb_edid_to_monspecs(edidB, monB); 527 } 528 529 if (slaved_on_A && !tvA) { 530 CRTCnumber = 0; 531 FlatPanel = 1; 532 printk("nvidiafb: CRTC 0 is currently programmed for " 533 "DFP\n"); 534 } else if (slaved_on_B && !tvB) { 535 CRTCnumber = 1; 536 FlatPanel = 1; 537 printk("nvidiafb: CRTC 1 is currently programmed " 538 "for DFP\n"); 539 } else if (analog_on_A) { 540 CRTCnumber = outputAfromCRTC; 541 FlatPanel = 0; 542 printk("nvidiafb: CRTC %i appears to have a " 543 "CRT attached\n", CRTCnumber); 544 } else if (analog_on_B) { 545 CRTCnumber = outputBfromCRTC; 546 FlatPanel = 0; 547 printk("nvidiafb: CRTC %i appears to have a " 548 "CRT attached\n", CRTCnumber); 549 } else if (slaved_on_A) { 550 CRTCnumber = 0; 551 FlatPanel = 1; 552 Television = 1; 553 printk("nvidiafb: CRTC 0 is currently programmed " 554 "for TV\n"); 555 } else if (slaved_on_B) { 556 CRTCnumber = 1; 557 FlatPanel = 1; 558 Television = 1; 559 printk("nvidiafb: CRTC 1 is currently programmed for " 560 "TV\n"); 561 } else if (monA) { 562 FlatPanel = (monA->input & FB_DISP_DDI) ? 1 : 0; 563 } else if (monB) { 564 FlatPanel = (monB->input & FB_DISP_DDI) ? 1 : 0; 565 } 566 567 if (par->FlatPanel == -1) { 568 if (FlatPanel != -1) { 569 par->FlatPanel = FlatPanel; 570 par->Television = Television; 571 } else { 572 printk("nvidiafb: Unable to detect display " 573 "type...\n"); 574 if (mobile) { 575 printk("...On a laptop, assuming " 576 "DFP\n"); 577 par->FlatPanel = 1; 578 } else { 579 printk("...Using default of CRT\n"); 580 par->FlatPanel = 0; 581 } 582 } 583 } else { 584 printk("nvidiafb: Forcing display type to %s as " 585 "specified\n", par->FlatPanel ? "DFP" : "CRT"); 586 } 587 588 if (par->CRTCnumber == -1) { 589 if (CRTCnumber != -1) 590 par->CRTCnumber = CRTCnumber; 591 else { 592 printk("nvidiafb: Unable to detect which " 593 "CRTCNumber...\n"); 594 if (par->FlatPanel) 595 par->CRTCnumber = 1; 596 else 597 par->CRTCnumber = 0; 598 printk("...Defaulting to CRTCNumber %i\n", 599 par->CRTCnumber); 600 } 601 } else { 602 printk("nvidiafb: Forcing CRTCNumber %i as " 603 "specified\n", par->CRTCnumber); 604 } 605 606 if (monA) { 607 if (((monA->input & FB_DISP_DDI) && 608 par->FlatPanel) || 609 ((!(monA->input & FB_DISP_DDI)) && 610 !par->FlatPanel)) { 611 if (monB) { 612 fb_destroy_modedb(monB->modedb); 613 monB = NULL; 614 } 615 } else { 616 fb_destroy_modedb(monA->modedb); 617 monA = NULL; 618 } 619 } 620 621 if (monB) { 622 if (((monB->input & FB_DISP_DDI) && 623 !par->FlatPanel) || 624 ((!(monB->input & FB_DISP_DDI)) && 625 par->FlatPanel)) { 626 fb_destroy_modedb(monB->modedb); 627 monB = NULL; 628 } else 629 monA = monB; 630 } 631 632 if (implementation == 0x0110) 633 cr44 = par->CRTCnumber * 0x3; 634 635 NV_WR32(par->PCRTC0, 0x00000860, oldhead); 636 637 VGA_WR08(par->PCIO, 0x03D4, 0x44); 638 VGA_WR08(par->PCIO, 0x03D5, cr44); 639 NVSelectHeadRegisters(par, par->CRTCnumber); 640 } 641 642 printk("nvidiafb: Using %s on CRTC %i\n", 643 par->FlatPanel ? (par->Television ? "TV" : "DFP") : "CRT", 644 par->CRTCnumber); 645 646 if (par->FlatPanel && !par->Television) { 647 par->fpWidth = NV_RD32(par->PRAMDAC, 0x0820) + 1; 648 par->fpHeight = NV_RD32(par->PRAMDAC, 0x0800) + 1; 649 par->fpSyncs = NV_RD32(par->PRAMDAC, 0x0848) & 0x30000033; 650 651 printk("nvidiafb: Panel size is %i x %i\n", par->fpWidth, par->fpHeight); 652 } 653 654 if (monA) 655 info->monspecs = *monA; 656 657 if (!par->FlatPanel || !par->twoHeads) 658 par->FPDither = 0; 659 660 par->LVDS = 0; 661 if (par->FlatPanel && par->twoHeads) { 662 NV_WR32(par->PRAMDAC0, 0x08B0, 0x00010004); 663 if (NV_RD32(par->PRAMDAC0, 0x08b4) & 1) 664 par->LVDS = 1; 665 printk("nvidiafb: Panel is %s\n", par->LVDS ? "LVDS" : "TMDS"); 666 } 667 668 kfree(edidA); 669 kfree(edidB); 670done: 671 kfree(var); 672 kfree(monitorA); 673 kfree(monitorB); 674 return err; 675} 676