18c2ecf20Sopenharmony_ci /***************************************************************************\ 28c2ecf20Sopenharmony_ci|* *| 38c2ecf20Sopenharmony_ci|* Copyright 2003 NVIDIA, Corporation. All rights reserved. *| 48c2ecf20Sopenharmony_ci|* *| 58c2ecf20Sopenharmony_ci|* NOTICE TO USER: The source code is copyrighted under U.S. and *| 68c2ecf20Sopenharmony_ci|* international laws. Users and possessors of this source code are *| 78c2ecf20Sopenharmony_ci|* hereby granted a nonexclusive, royalty-free copyright license to *| 88c2ecf20Sopenharmony_ci|* use this code in individual and commercial software. *| 98c2ecf20Sopenharmony_ci|* *| 108c2ecf20Sopenharmony_ci|* Any use of this source code must include, in the user documenta- *| 118c2ecf20Sopenharmony_ci|* tion and internal comments to the code, notices to the end user *| 128c2ecf20Sopenharmony_ci|* as follows: *| 138c2ecf20Sopenharmony_ci|* *| 148c2ecf20Sopenharmony_ci|* Copyright 2003 NVIDIA, Corporation. All rights reserved. *| 158c2ecf20Sopenharmony_ci|* *| 168c2ecf20Sopenharmony_ci|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *| 178c2ecf20Sopenharmony_ci|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *| 188c2ecf20Sopenharmony_ci|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *| 198c2ecf20Sopenharmony_ci|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *| 208c2ecf20Sopenharmony_ci|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *| 218c2ecf20Sopenharmony_ci|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *| 228c2ecf20Sopenharmony_ci|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *| 238c2ecf20Sopenharmony_ci|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *| 248c2ecf20Sopenharmony_ci|* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *| 258c2ecf20Sopenharmony_ci|* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *| 268c2ecf20Sopenharmony_ci|* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *| 278c2ecf20Sopenharmony_ci|* *| 288c2ecf20Sopenharmony_ci|* U.S. Government End Users. This source code is a "commercial *| 298c2ecf20Sopenharmony_ci|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *| 308c2ecf20Sopenharmony_ci|* consisting of "commercial computer software" and "commercial *| 318c2ecf20Sopenharmony_ci|* computer software documentation," as such terms are used in *| 328c2ecf20Sopenharmony_ci|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *| 338c2ecf20Sopenharmony_ci|* ment only as a commercial end item. Consistent with 48 C.F.R. *| 348c2ecf20Sopenharmony_ci|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *| 358c2ecf20Sopenharmony_ci|* all U.S. Government End Users acquire the source code with only *| 368c2ecf20Sopenharmony_ci|* those rights set forth herein. *| 378c2ecf20Sopenharmony_ci|* *| 388c2ecf20Sopenharmony_ci \***************************************************************************/ 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci/* 418c2ecf20Sopenharmony_ci * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/ 428c2ecf20Sopenharmony_ci * XFree86 'nv' driver, this source code is provided under MIT-style licensing 438c2ecf20Sopenharmony_ci * where the source code is provided "as is" without warranty of any kind. 448c2ecf20Sopenharmony_ci * The only usage restriction is for the copyright notices to be retained 458c2ecf20Sopenharmony_ci * whenever code is used. 468c2ecf20Sopenharmony_ci * 478c2ecf20Sopenharmony_ci * Antonino Daplas <adaplas@pol.net> 2005-03-11 488c2ecf20Sopenharmony_ci */ 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci#include <video/vga.h> 518c2ecf20Sopenharmony_ci#include <linux/delay.h> 528c2ecf20Sopenharmony_ci#include <linux/pci.h> 538c2ecf20Sopenharmony_ci#include <linux/slab.h> 548c2ecf20Sopenharmony_ci#include "nv_type.h" 558c2ecf20Sopenharmony_ci#include "nv_local.h" 568c2ecf20Sopenharmony_ci#include "nv_proto.h" 578c2ecf20Sopenharmony_ci/* 588c2ecf20Sopenharmony_ci * Override VGA I/O routines. 598c2ecf20Sopenharmony_ci */ 608c2ecf20Sopenharmony_civoid NVWriteCrtc(struct nvidia_par *par, u8 index, u8 value) 618c2ecf20Sopenharmony_ci{ 628c2ecf20Sopenharmony_ci VGA_WR08(par->PCIO, par->IOBase + 0x04, index); 638c2ecf20Sopenharmony_ci VGA_WR08(par->PCIO, par->IOBase + 0x05, value); 648c2ecf20Sopenharmony_ci} 658c2ecf20Sopenharmony_ciu8 NVReadCrtc(struct nvidia_par *par, u8 index) 668c2ecf20Sopenharmony_ci{ 678c2ecf20Sopenharmony_ci VGA_WR08(par->PCIO, par->IOBase + 0x04, index); 688c2ecf20Sopenharmony_ci return (VGA_RD08(par->PCIO, par->IOBase + 0x05)); 698c2ecf20Sopenharmony_ci} 708c2ecf20Sopenharmony_civoid NVWriteGr(struct nvidia_par *par, u8 index, u8 value) 718c2ecf20Sopenharmony_ci{ 728c2ecf20Sopenharmony_ci VGA_WR08(par->PVIO, VGA_GFX_I, index); 738c2ecf20Sopenharmony_ci VGA_WR08(par->PVIO, VGA_GFX_D, value); 748c2ecf20Sopenharmony_ci} 758c2ecf20Sopenharmony_ciu8 NVReadGr(struct nvidia_par *par, u8 index) 768c2ecf20Sopenharmony_ci{ 778c2ecf20Sopenharmony_ci VGA_WR08(par->PVIO, VGA_GFX_I, index); 788c2ecf20Sopenharmony_ci return (VGA_RD08(par->PVIO, VGA_GFX_D)); 798c2ecf20Sopenharmony_ci} 808c2ecf20Sopenharmony_civoid NVWriteSeq(struct nvidia_par *par, u8 index, u8 value) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci VGA_WR08(par->PVIO, VGA_SEQ_I, index); 838c2ecf20Sopenharmony_ci VGA_WR08(par->PVIO, VGA_SEQ_D, value); 848c2ecf20Sopenharmony_ci} 858c2ecf20Sopenharmony_ciu8 NVReadSeq(struct nvidia_par *par, u8 index) 868c2ecf20Sopenharmony_ci{ 878c2ecf20Sopenharmony_ci VGA_WR08(par->PVIO, VGA_SEQ_I, index); 888c2ecf20Sopenharmony_ci return (VGA_RD08(par->PVIO, VGA_SEQ_D)); 898c2ecf20Sopenharmony_ci} 908c2ecf20Sopenharmony_civoid NVWriteAttr(struct nvidia_par *par, u8 index, u8 value) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci volatile u8 tmp; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci tmp = VGA_RD08(par->PCIO, par->IOBase + 0x0a); 958c2ecf20Sopenharmony_ci if (par->paletteEnabled) 968c2ecf20Sopenharmony_ci index &= ~0x20; 978c2ecf20Sopenharmony_ci else 988c2ecf20Sopenharmony_ci index |= 0x20; 998c2ecf20Sopenharmony_ci VGA_WR08(par->PCIO, VGA_ATT_IW, index); 1008c2ecf20Sopenharmony_ci VGA_WR08(par->PCIO, VGA_ATT_W, value); 1018c2ecf20Sopenharmony_ci} 1028c2ecf20Sopenharmony_ciu8 NVReadAttr(struct nvidia_par *par, u8 index) 1038c2ecf20Sopenharmony_ci{ 1048c2ecf20Sopenharmony_ci volatile u8 tmp; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci tmp = VGA_RD08(par->PCIO, par->IOBase + 0x0a); 1078c2ecf20Sopenharmony_ci if (par->paletteEnabled) 1088c2ecf20Sopenharmony_ci index &= ~0x20; 1098c2ecf20Sopenharmony_ci else 1108c2ecf20Sopenharmony_ci index |= 0x20; 1118c2ecf20Sopenharmony_ci VGA_WR08(par->PCIO, VGA_ATT_IW, index); 1128c2ecf20Sopenharmony_ci return (VGA_RD08(par->PCIO, VGA_ATT_R)); 1138c2ecf20Sopenharmony_ci} 1148c2ecf20Sopenharmony_civoid NVWriteMiscOut(struct nvidia_par *par, u8 value) 1158c2ecf20Sopenharmony_ci{ 1168c2ecf20Sopenharmony_ci VGA_WR08(par->PVIO, VGA_MIS_W, value); 1178c2ecf20Sopenharmony_ci} 1188c2ecf20Sopenharmony_ciu8 NVReadMiscOut(struct nvidia_par *par) 1198c2ecf20Sopenharmony_ci{ 1208c2ecf20Sopenharmony_ci return (VGA_RD08(par->PVIO, VGA_MIS_R)); 1218c2ecf20Sopenharmony_ci} 1228c2ecf20Sopenharmony_civoid NVWriteDacMask(struct nvidia_par *par, u8 value) 1238c2ecf20Sopenharmony_ci{ 1248c2ecf20Sopenharmony_ci VGA_WR08(par->PDIO, VGA_PEL_MSK, value); 1258c2ecf20Sopenharmony_ci} 1268c2ecf20Sopenharmony_civoid NVWriteDacReadAddr(struct nvidia_par *par, u8 value) 1278c2ecf20Sopenharmony_ci{ 1288c2ecf20Sopenharmony_ci VGA_WR08(par->PDIO, VGA_PEL_IR, value); 1298c2ecf20Sopenharmony_ci} 1308c2ecf20Sopenharmony_civoid NVWriteDacWriteAddr(struct nvidia_par *par, u8 value) 1318c2ecf20Sopenharmony_ci{ 1328c2ecf20Sopenharmony_ci VGA_WR08(par->PDIO, VGA_PEL_IW, value); 1338c2ecf20Sopenharmony_ci} 1348c2ecf20Sopenharmony_civoid NVWriteDacData(struct nvidia_par *par, u8 value) 1358c2ecf20Sopenharmony_ci{ 1368c2ecf20Sopenharmony_ci VGA_WR08(par->PDIO, VGA_PEL_D, value); 1378c2ecf20Sopenharmony_ci} 1388c2ecf20Sopenharmony_ciu8 NVReadDacData(struct nvidia_par *par) 1398c2ecf20Sopenharmony_ci{ 1408c2ecf20Sopenharmony_ci return (VGA_RD08(par->PDIO, VGA_PEL_D)); 1418c2ecf20Sopenharmony_ci} 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_cistatic int NVIsConnected(struct nvidia_par *par, int output) 1448c2ecf20Sopenharmony_ci{ 1458c2ecf20Sopenharmony_ci volatile u32 __iomem *PRAMDAC = par->PRAMDAC0; 1468c2ecf20Sopenharmony_ci u32 reg52C, reg608, dac0_reg608 = 0; 1478c2ecf20Sopenharmony_ci int present; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci if (output) { 1508c2ecf20Sopenharmony_ci dac0_reg608 = NV_RD32(PRAMDAC, 0x0608); 1518c2ecf20Sopenharmony_ci PRAMDAC += 0x800; 1528c2ecf20Sopenharmony_ci } 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci reg52C = NV_RD32(PRAMDAC, 0x052C); 1558c2ecf20Sopenharmony_ci reg608 = NV_RD32(PRAMDAC, 0x0608); 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci NV_WR32(PRAMDAC, 0x0608, reg608 & ~0x00010000); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci NV_WR32(PRAMDAC, 0x052C, reg52C & 0x0000FEEE); 1608c2ecf20Sopenharmony_ci msleep(1); 1618c2ecf20Sopenharmony_ci NV_WR32(PRAMDAC, 0x052C, NV_RD32(PRAMDAC, 0x052C) | 1); 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci NV_WR32(par->PRAMDAC0, 0x0610, 0x94050140); 1648c2ecf20Sopenharmony_ci NV_WR32(par->PRAMDAC0, 0x0608, NV_RD32(par->PRAMDAC0, 0x0608) | 1658c2ecf20Sopenharmony_ci 0x00001000); 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci msleep(1); 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci present = (NV_RD32(PRAMDAC, 0x0608) & (1 << 28)) ? 1 : 0; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci if (present) 1728c2ecf20Sopenharmony_ci printk("nvidiafb: CRTC%i analog found\n", output); 1738c2ecf20Sopenharmony_ci else 1748c2ecf20Sopenharmony_ci printk("nvidiafb: CRTC%i analog not found\n", output); 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci if (output) 1778c2ecf20Sopenharmony_ci NV_WR32(par->PRAMDAC0, 0x0608, dac0_reg608); 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci NV_WR32(PRAMDAC, 0x052C, reg52C); 1808c2ecf20Sopenharmony_ci NV_WR32(PRAMDAC, 0x0608, reg608); 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci return present; 1838c2ecf20Sopenharmony_ci} 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_cistatic void NVSelectHeadRegisters(struct nvidia_par *par, int head) 1868c2ecf20Sopenharmony_ci{ 1878c2ecf20Sopenharmony_ci if (head) { 1888c2ecf20Sopenharmony_ci par->PCIO = par->PCIO0 + 0x2000; 1898c2ecf20Sopenharmony_ci par->PCRTC = par->PCRTC0 + 0x800; 1908c2ecf20Sopenharmony_ci par->PRAMDAC = par->PRAMDAC0 + 0x800; 1918c2ecf20Sopenharmony_ci par->PDIO = par->PDIO0 + 0x2000; 1928c2ecf20Sopenharmony_ci } else { 1938c2ecf20Sopenharmony_ci par->PCIO = par->PCIO0; 1948c2ecf20Sopenharmony_ci par->PCRTC = par->PCRTC0; 1958c2ecf20Sopenharmony_ci par->PRAMDAC = par->PRAMDAC0; 1968c2ecf20Sopenharmony_ci par->PDIO = par->PDIO0; 1978c2ecf20Sopenharmony_ci } 1988c2ecf20Sopenharmony_ci} 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_cistatic void nv4GetConfig(struct nvidia_par *par) 2018c2ecf20Sopenharmony_ci{ 2028c2ecf20Sopenharmony_ci if (NV_RD32(par->PFB, 0x0000) & 0x00000100) { 2038c2ecf20Sopenharmony_ci par->RamAmountKBytes = 2048c2ecf20Sopenharmony_ci ((NV_RD32(par->PFB, 0x0000) >> 12) & 0x0F) * 1024 * 2 + 2058c2ecf20Sopenharmony_ci 1024 * 2; 2068c2ecf20Sopenharmony_ci } else { 2078c2ecf20Sopenharmony_ci switch (NV_RD32(par->PFB, 0x0000) & 0x00000003) { 2088c2ecf20Sopenharmony_ci case 0: 2098c2ecf20Sopenharmony_ci par->RamAmountKBytes = 1024 * 32; 2108c2ecf20Sopenharmony_ci break; 2118c2ecf20Sopenharmony_ci case 1: 2128c2ecf20Sopenharmony_ci par->RamAmountKBytes = 1024 * 4; 2138c2ecf20Sopenharmony_ci break; 2148c2ecf20Sopenharmony_ci case 2: 2158c2ecf20Sopenharmony_ci par->RamAmountKBytes = 1024 * 8; 2168c2ecf20Sopenharmony_ci break; 2178c2ecf20Sopenharmony_ci case 3: 2188c2ecf20Sopenharmony_ci default: 2198c2ecf20Sopenharmony_ci par->RamAmountKBytes = 1024 * 16; 2208c2ecf20Sopenharmony_ci break; 2218c2ecf20Sopenharmony_ci } 2228c2ecf20Sopenharmony_ci } 2238c2ecf20Sopenharmony_ci par->CrystalFreqKHz = (NV_RD32(par->PEXTDEV, 0x0000) & 0x00000040) ? 2248c2ecf20Sopenharmony_ci 14318 : 13500; 2258c2ecf20Sopenharmony_ci par->CURSOR = &par->PRAMIN[0x1E00]; 2268c2ecf20Sopenharmony_ci par->MinVClockFreqKHz = 12000; 2278c2ecf20Sopenharmony_ci par->MaxVClockFreqKHz = 350000; 2288c2ecf20Sopenharmony_ci} 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_cistatic void nv10GetConfig(struct nvidia_par *par) 2318c2ecf20Sopenharmony_ci{ 2328c2ecf20Sopenharmony_ci struct pci_dev *dev; 2338c2ecf20Sopenharmony_ci u32 implementation = par->Chipset & 0x0ff0; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci#ifdef __BIG_ENDIAN 2368c2ecf20Sopenharmony_ci /* turn on big endian register access */ 2378c2ecf20Sopenharmony_ci if (!(NV_RD32(par->PMC, 0x0004) & 0x01000001)) { 2388c2ecf20Sopenharmony_ci NV_WR32(par->PMC, 0x0004, 0x01000001); 2398c2ecf20Sopenharmony_ci mb(); 2408c2ecf20Sopenharmony_ci } 2418c2ecf20Sopenharmony_ci#endif 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci dev = pci_get_domain_bus_and_slot(pci_domain_nr(par->pci_dev->bus), 2448c2ecf20Sopenharmony_ci 0, 1); 2458c2ecf20Sopenharmony_ci if ((par->Chipset & 0xffff) == 0x01a0) { 2468c2ecf20Sopenharmony_ci u32 amt; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci pci_read_config_dword(dev, 0x7c, &amt); 2498c2ecf20Sopenharmony_ci par->RamAmountKBytes = (((amt >> 6) & 31) + 1) * 1024; 2508c2ecf20Sopenharmony_ci } else if ((par->Chipset & 0xffff) == 0x01f0) { 2518c2ecf20Sopenharmony_ci u32 amt; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci pci_read_config_dword(dev, 0x84, &amt); 2548c2ecf20Sopenharmony_ci par->RamAmountKBytes = (((amt >> 4) & 127) + 1) * 1024; 2558c2ecf20Sopenharmony_ci } else { 2568c2ecf20Sopenharmony_ci par->RamAmountKBytes = 2578c2ecf20Sopenharmony_ci (NV_RD32(par->PFB, 0x020C) & 0xFFF00000) >> 10; 2588c2ecf20Sopenharmony_ci } 2598c2ecf20Sopenharmony_ci pci_dev_put(dev); 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci par->CrystalFreqKHz = (NV_RD32(par->PEXTDEV, 0x0000) & (1 << 6)) ? 2628c2ecf20Sopenharmony_ci 14318 : 13500; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci if (par->twoHeads && (implementation != 0x0110)) { 2658c2ecf20Sopenharmony_ci if (NV_RD32(par->PEXTDEV, 0x0000) & (1 << 22)) 2668c2ecf20Sopenharmony_ci par->CrystalFreqKHz = 27000; 2678c2ecf20Sopenharmony_ci } 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci par->CURSOR = NULL; /* can't set this here */ 2708c2ecf20Sopenharmony_ci par->MinVClockFreqKHz = 12000; 2718c2ecf20Sopenharmony_ci par->MaxVClockFreqKHz = par->twoStagePLL ? 400000 : 350000; 2728c2ecf20Sopenharmony_ci} 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ciint NVCommonSetup(struct fb_info *info) 2758c2ecf20Sopenharmony_ci{ 2768c2ecf20Sopenharmony_ci struct nvidia_par *par = info->par; 2778c2ecf20Sopenharmony_ci struct fb_var_screeninfo *var; 2788c2ecf20Sopenharmony_ci u16 implementation = par->Chipset & 0x0ff0; 2798c2ecf20Sopenharmony_ci u8 *edidA = NULL, *edidB = NULL; 2808c2ecf20Sopenharmony_ci struct fb_monspecs *monitorA, *monitorB; 2818c2ecf20Sopenharmony_ci struct fb_monspecs *monA = NULL, *monB = NULL; 2828c2ecf20Sopenharmony_ci int mobile = 0; 2838c2ecf20Sopenharmony_ci int tvA = 0; 2848c2ecf20Sopenharmony_ci int tvB = 0; 2858c2ecf20Sopenharmony_ci int FlatPanel = -1; /* really means the CRTC is slaved */ 2868c2ecf20Sopenharmony_ci int Television = 0; 2878c2ecf20Sopenharmony_ci int err = 0; 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci var = kzalloc(sizeof(struct fb_var_screeninfo), GFP_KERNEL); 2908c2ecf20Sopenharmony_ci monitorA = kzalloc(sizeof(struct fb_monspecs), GFP_KERNEL); 2918c2ecf20Sopenharmony_ci monitorB = kzalloc(sizeof(struct fb_monspecs), GFP_KERNEL); 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci if (!var || !monitorA || !monitorB) { 2948c2ecf20Sopenharmony_ci err = -ENOMEM; 2958c2ecf20Sopenharmony_ci goto done; 2968c2ecf20Sopenharmony_ci } 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci par->PRAMIN = par->REGS + (0x00710000 / 4); 2998c2ecf20Sopenharmony_ci par->PCRTC0 = par->REGS + (0x00600000 / 4); 3008c2ecf20Sopenharmony_ci par->PRAMDAC0 = par->REGS + (0x00680000 / 4); 3018c2ecf20Sopenharmony_ci par->PFB = par->REGS + (0x00100000 / 4); 3028c2ecf20Sopenharmony_ci par->PFIFO = par->REGS + (0x00002000 / 4); 3038c2ecf20Sopenharmony_ci par->PGRAPH = par->REGS + (0x00400000 / 4); 3048c2ecf20Sopenharmony_ci par->PEXTDEV = par->REGS + (0x00101000 / 4); 3058c2ecf20Sopenharmony_ci par->PTIMER = par->REGS + (0x00009000 / 4); 3068c2ecf20Sopenharmony_ci par->PMC = par->REGS + (0x00000000 / 4); 3078c2ecf20Sopenharmony_ci par->FIFO = par->REGS + (0x00800000 / 4); 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci /* 8 bit registers */ 3108c2ecf20Sopenharmony_ci par->PCIO0 = (u8 __iomem *) par->REGS + 0x00601000; 3118c2ecf20Sopenharmony_ci par->PDIO0 = (u8 __iomem *) par->REGS + 0x00681000; 3128c2ecf20Sopenharmony_ci par->PVIO = (u8 __iomem *) par->REGS + 0x000C0000; 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci par->twoHeads = (par->Architecture >= NV_ARCH_10) && 3158c2ecf20Sopenharmony_ci (implementation != 0x0100) && 3168c2ecf20Sopenharmony_ci (implementation != 0x0150) && 3178c2ecf20Sopenharmony_ci (implementation != 0x01A0) && (implementation != 0x0200); 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci par->fpScaler = (par->FpScale && par->twoHeads && 3208c2ecf20Sopenharmony_ci (implementation != 0x0110)); 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci par->twoStagePLL = (implementation == 0x0310) || 3238c2ecf20Sopenharmony_ci (implementation == 0x0340) || (par->Architecture >= NV_ARCH_40); 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci par->WaitVSyncPossible = (par->Architecture >= NV_ARCH_10) && 3268c2ecf20Sopenharmony_ci (implementation != 0x0100); 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci par->BlendingPossible = ((par->Chipset & 0xffff) != 0x0020); 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci /* look for known laptop chips */ 3318c2ecf20Sopenharmony_ci switch (par->Chipset & 0xffff) { 3328c2ecf20Sopenharmony_ci case 0x0112: 3338c2ecf20Sopenharmony_ci case 0x0174: 3348c2ecf20Sopenharmony_ci case 0x0175: 3358c2ecf20Sopenharmony_ci case 0x0176: 3368c2ecf20Sopenharmony_ci case 0x0177: 3378c2ecf20Sopenharmony_ci case 0x0179: 3388c2ecf20Sopenharmony_ci case 0x017C: 3398c2ecf20Sopenharmony_ci case 0x017D: 3408c2ecf20Sopenharmony_ci case 0x0186: 3418c2ecf20Sopenharmony_ci case 0x0187: 3428c2ecf20Sopenharmony_ci case 0x018D: 3438c2ecf20Sopenharmony_ci case 0x01D7: 3448c2ecf20Sopenharmony_ci case 0x0228: 3458c2ecf20Sopenharmony_ci case 0x0286: 3468c2ecf20Sopenharmony_ci case 0x028C: 3478c2ecf20Sopenharmony_ci case 0x0316: 3488c2ecf20Sopenharmony_ci case 0x0317: 3498c2ecf20Sopenharmony_ci case 0x031A: 3508c2ecf20Sopenharmony_ci case 0x031B: 3518c2ecf20Sopenharmony_ci case 0x031C: 3528c2ecf20Sopenharmony_ci case 0x031D: 3538c2ecf20Sopenharmony_ci case 0x031E: 3548c2ecf20Sopenharmony_ci case 0x031F: 3558c2ecf20Sopenharmony_ci case 0x0324: 3568c2ecf20Sopenharmony_ci case 0x0325: 3578c2ecf20Sopenharmony_ci case 0x0328: 3588c2ecf20Sopenharmony_ci case 0x0329: 3598c2ecf20Sopenharmony_ci case 0x032C: 3608c2ecf20Sopenharmony_ci case 0x032D: 3618c2ecf20Sopenharmony_ci case 0x0347: 3628c2ecf20Sopenharmony_ci case 0x0348: 3638c2ecf20Sopenharmony_ci case 0x0349: 3648c2ecf20Sopenharmony_ci case 0x034B: 3658c2ecf20Sopenharmony_ci case 0x034C: 3668c2ecf20Sopenharmony_ci case 0x0160: 3678c2ecf20Sopenharmony_ci case 0x0166: 3688c2ecf20Sopenharmony_ci case 0x0169: 3698c2ecf20Sopenharmony_ci case 0x016B: 3708c2ecf20Sopenharmony_ci case 0x016C: 3718c2ecf20Sopenharmony_ci case 0x016D: 3728c2ecf20Sopenharmony_ci case 0x00C8: 3738c2ecf20Sopenharmony_ci case 0x00CC: 3748c2ecf20Sopenharmony_ci case 0x0144: 3758c2ecf20Sopenharmony_ci case 0x0146: 3768c2ecf20Sopenharmony_ci case 0x0147: 3778c2ecf20Sopenharmony_ci case 0x0148: 3788c2ecf20Sopenharmony_ci case 0x0098: 3798c2ecf20Sopenharmony_ci case 0x0099: 3808c2ecf20Sopenharmony_ci mobile = 1; 3818c2ecf20Sopenharmony_ci break; 3828c2ecf20Sopenharmony_ci default: 3838c2ecf20Sopenharmony_ci break; 3848c2ecf20Sopenharmony_ci } 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci if (par->Architecture == NV_ARCH_04) 3878c2ecf20Sopenharmony_ci nv4GetConfig(par); 3888c2ecf20Sopenharmony_ci else 3898c2ecf20Sopenharmony_ci nv10GetConfig(par); 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci NVSelectHeadRegisters(par, 0); 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci NVLockUnlock(par, 0); 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci par->IOBase = (NVReadMiscOut(par) & 0x01) ? 0x3d0 : 0x3b0; 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci par->Television = 0; 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci nvidia_create_i2c_busses(par); 4008c2ecf20Sopenharmony_ci if (!par->twoHeads) { 4018c2ecf20Sopenharmony_ci par->CRTCnumber = 0; 4028c2ecf20Sopenharmony_ci if (nvidia_probe_i2c_connector(info, 1, &edidA)) 4038c2ecf20Sopenharmony_ci nvidia_probe_of_connector(info, 1, &edidA); 4048c2ecf20Sopenharmony_ci if (edidA && !fb_parse_edid(edidA, var)) { 4058c2ecf20Sopenharmony_ci printk("nvidiafb: EDID found from BUS1\n"); 4068c2ecf20Sopenharmony_ci monA = monitorA; 4078c2ecf20Sopenharmony_ci fb_edid_to_monspecs(edidA, monA); 4088c2ecf20Sopenharmony_ci FlatPanel = (monA->input & FB_DISP_DDI) ? 1 : 0; 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci /* NV4 doesn't support FlatPanels */ 4118c2ecf20Sopenharmony_ci if ((par->Chipset & 0x0fff) <= 0x0020) 4128c2ecf20Sopenharmony_ci FlatPanel = 0; 4138c2ecf20Sopenharmony_ci } else { 4148c2ecf20Sopenharmony_ci VGA_WR08(par->PCIO, 0x03D4, 0x28); 4158c2ecf20Sopenharmony_ci if (VGA_RD08(par->PCIO, 0x03D5) & 0x80) { 4168c2ecf20Sopenharmony_ci VGA_WR08(par->PCIO, 0x03D4, 0x33); 4178c2ecf20Sopenharmony_ci if (!(VGA_RD08(par->PCIO, 0x03D5) & 0x01)) 4188c2ecf20Sopenharmony_ci Television = 1; 4198c2ecf20Sopenharmony_ci FlatPanel = 1; 4208c2ecf20Sopenharmony_ci } else { 4218c2ecf20Sopenharmony_ci FlatPanel = 0; 4228c2ecf20Sopenharmony_ci } 4238c2ecf20Sopenharmony_ci printk("nvidiafb: HW is currently programmed for %s\n", 4248c2ecf20Sopenharmony_ci FlatPanel ? (Television ? "TV" : "DFP") : 4258c2ecf20Sopenharmony_ci "CRT"); 4268c2ecf20Sopenharmony_ci } 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci if (par->FlatPanel == -1) { 4298c2ecf20Sopenharmony_ci par->FlatPanel = FlatPanel; 4308c2ecf20Sopenharmony_ci par->Television = Television; 4318c2ecf20Sopenharmony_ci } else { 4328c2ecf20Sopenharmony_ci printk("nvidiafb: Forcing display type to %s as " 4338c2ecf20Sopenharmony_ci "specified\n", par->FlatPanel ? "DFP" : "CRT"); 4348c2ecf20Sopenharmony_ci } 4358c2ecf20Sopenharmony_ci } else { 4368c2ecf20Sopenharmony_ci u8 outputAfromCRTC, outputBfromCRTC; 4378c2ecf20Sopenharmony_ci int CRTCnumber = -1; 4388c2ecf20Sopenharmony_ci u8 slaved_on_A, slaved_on_B; 4398c2ecf20Sopenharmony_ci int analog_on_A, analog_on_B; 4408c2ecf20Sopenharmony_ci u32 oldhead; 4418c2ecf20Sopenharmony_ci u8 cr44; 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci if (implementation != 0x0110) { 4448c2ecf20Sopenharmony_ci if (NV_RD32(par->PRAMDAC0, 0x0000052C) & 0x100) 4458c2ecf20Sopenharmony_ci outputAfromCRTC = 1; 4468c2ecf20Sopenharmony_ci else 4478c2ecf20Sopenharmony_ci outputAfromCRTC = 0; 4488c2ecf20Sopenharmony_ci if (NV_RD32(par->PRAMDAC0, 0x0000252C) & 0x100) 4498c2ecf20Sopenharmony_ci outputBfromCRTC = 1; 4508c2ecf20Sopenharmony_ci else 4518c2ecf20Sopenharmony_ci outputBfromCRTC = 0; 4528c2ecf20Sopenharmony_ci analog_on_A = NVIsConnected(par, 0); 4538c2ecf20Sopenharmony_ci analog_on_B = NVIsConnected(par, 1); 4548c2ecf20Sopenharmony_ci } else { 4558c2ecf20Sopenharmony_ci outputAfromCRTC = 0; 4568c2ecf20Sopenharmony_ci outputBfromCRTC = 1; 4578c2ecf20Sopenharmony_ci analog_on_A = 0; 4588c2ecf20Sopenharmony_ci analog_on_B = 0; 4598c2ecf20Sopenharmony_ci } 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci VGA_WR08(par->PCIO, 0x03D4, 0x44); 4628c2ecf20Sopenharmony_ci cr44 = VGA_RD08(par->PCIO, 0x03D5); 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci VGA_WR08(par->PCIO, 0x03D5, 3); 4658c2ecf20Sopenharmony_ci NVSelectHeadRegisters(par, 1); 4668c2ecf20Sopenharmony_ci NVLockUnlock(par, 0); 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci VGA_WR08(par->PCIO, 0x03D4, 0x28); 4698c2ecf20Sopenharmony_ci slaved_on_B = VGA_RD08(par->PCIO, 0x03D5) & 0x80; 4708c2ecf20Sopenharmony_ci if (slaved_on_B) { 4718c2ecf20Sopenharmony_ci VGA_WR08(par->PCIO, 0x03D4, 0x33); 4728c2ecf20Sopenharmony_ci tvB = !(VGA_RD08(par->PCIO, 0x03D5) & 0x01); 4738c2ecf20Sopenharmony_ci } 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci VGA_WR08(par->PCIO, 0x03D4, 0x44); 4768c2ecf20Sopenharmony_ci VGA_WR08(par->PCIO, 0x03D5, 0); 4778c2ecf20Sopenharmony_ci NVSelectHeadRegisters(par, 0); 4788c2ecf20Sopenharmony_ci NVLockUnlock(par, 0); 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci VGA_WR08(par->PCIO, 0x03D4, 0x28); 4818c2ecf20Sopenharmony_ci slaved_on_A = VGA_RD08(par->PCIO, 0x03D5) & 0x80; 4828c2ecf20Sopenharmony_ci if (slaved_on_A) { 4838c2ecf20Sopenharmony_ci VGA_WR08(par->PCIO, 0x03D4, 0x33); 4848c2ecf20Sopenharmony_ci tvA = !(VGA_RD08(par->PCIO, 0x03D5) & 0x01); 4858c2ecf20Sopenharmony_ci } 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci oldhead = NV_RD32(par->PCRTC0, 0x00000860); 4888c2ecf20Sopenharmony_ci NV_WR32(par->PCRTC0, 0x00000860, oldhead | 0x00000010); 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci if (nvidia_probe_i2c_connector(info, 1, &edidA)) 4918c2ecf20Sopenharmony_ci nvidia_probe_of_connector(info, 1, &edidA); 4928c2ecf20Sopenharmony_ci if (edidA && !fb_parse_edid(edidA, var)) { 4938c2ecf20Sopenharmony_ci printk("nvidiafb: EDID found from BUS1\n"); 4948c2ecf20Sopenharmony_ci monA = monitorA; 4958c2ecf20Sopenharmony_ci fb_edid_to_monspecs(edidA, monA); 4968c2ecf20Sopenharmony_ci } 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci if (nvidia_probe_i2c_connector(info, 2, &edidB)) 4998c2ecf20Sopenharmony_ci nvidia_probe_of_connector(info, 2, &edidB); 5008c2ecf20Sopenharmony_ci if (edidB && !fb_parse_edid(edidB, var)) { 5018c2ecf20Sopenharmony_ci printk("nvidiafb: EDID found from BUS2\n"); 5028c2ecf20Sopenharmony_ci monB = monitorB; 5038c2ecf20Sopenharmony_ci fb_edid_to_monspecs(edidB, monB); 5048c2ecf20Sopenharmony_ci } 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ci if (slaved_on_A && !tvA) { 5078c2ecf20Sopenharmony_ci CRTCnumber = 0; 5088c2ecf20Sopenharmony_ci FlatPanel = 1; 5098c2ecf20Sopenharmony_ci printk("nvidiafb: CRTC 0 is currently programmed for " 5108c2ecf20Sopenharmony_ci "DFP\n"); 5118c2ecf20Sopenharmony_ci } else if (slaved_on_B && !tvB) { 5128c2ecf20Sopenharmony_ci CRTCnumber = 1; 5138c2ecf20Sopenharmony_ci FlatPanel = 1; 5148c2ecf20Sopenharmony_ci printk("nvidiafb: CRTC 1 is currently programmed " 5158c2ecf20Sopenharmony_ci "for DFP\n"); 5168c2ecf20Sopenharmony_ci } else if (analog_on_A) { 5178c2ecf20Sopenharmony_ci CRTCnumber = outputAfromCRTC; 5188c2ecf20Sopenharmony_ci FlatPanel = 0; 5198c2ecf20Sopenharmony_ci printk("nvidiafb: CRTC %i appears to have a " 5208c2ecf20Sopenharmony_ci "CRT attached\n", CRTCnumber); 5218c2ecf20Sopenharmony_ci } else if (analog_on_B) { 5228c2ecf20Sopenharmony_ci CRTCnumber = outputBfromCRTC; 5238c2ecf20Sopenharmony_ci FlatPanel = 0; 5248c2ecf20Sopenharmony_ci printk("nvidiafb: CRTC %i appears to have a " 5258c2ecf20Sopenharmony_ci "CRT attached\n", CRTCnumber); 5268c2ecf20Sopenharmony_ci } else if (slaved_on_A) { 5278c2ecf20Sopenharmony_ci CRTCnumber = 0; 5288c2ecf20Sopenharmony_ci FlatPanel = 1; 5298c2ecf20Sopenharmony_ci Television = 1; 5308c2ecf20Sopenharmony_ci printk("nvidiafb: CRTC 0 is currently programmed " 5318c2ecf20Sopenharmony_ci "for TV\n"); 5328c2ecf20Sopenharmony_ci } else if (slaved_on_B) { 5338c2ecf20Sopenharmony_ci CRTCnumber = 1; 5348c2ecf20Sopenharmony_ci FlatPanel = 1; 5358c2ecf20Sopenharmony_ci Television = 1; 5368c2ecf20Sopenharmony_ci printk("nvidiafb: CRTC 1 is currently programmed for " 5378c2ecf20Sopenharmony_ci "TV\n"); 5388c2ecf20Sopenharmony_ci } else if (monA) { 5398c2ecf20Sopenharmony_ci FlatPanel = (monA->input & FB_DISP_DDI) ? 1 : 0; 5408c2ecf20Sopenharmony_ci } else if (monB) { 5418c2ecf20Sopenharmony_ci FlatPanel = (monB->input & FB_DISP_DDI) ? 1 : 0; 5428c2ecf20Sopenharmony_ci } 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci if (par->FlatPanel == -1) { 5458c2ecf20Sopenharmony_ci if (FlatPanel != -1) { 5468c2ecf20Sopenharmony_ci par->FlatPanel = FlatPanel; 5478c2ecf20Sopenharmony_ci par->Television = Television; 5488c2ecf20Sopenharmony_ci } else { 5498c2ecf20Sopenharmony_ci printk("nvidiafb: Unable to detect display " 5508c2ecf20Sopenharmony_ci "type...\n"); 5518c2ecf20Sopenharmony_ci if (mobile) { 5528c2ecf20Sopenharmony_ci printk("...On a laptop, assuming " 5538c2ecf20Sopenharmony_ci "DFP\n"); 5548c2ecf20Sopenharmony_ci par->FlatPanel = 1; 5558c2ecf20Sopenharmony_ci } else { 5568c2ecf20Sopenharmony_ci printk("...Using default of CRT\n"); 5578c2ecf20Sopenharmony_ci par->FlatPanel = 0; 5588c2ecf20Sopenharmony_ci } 5598c2ecf20Sopenharmony_ci } 5608c2ecf20Sopenharmony_ci } else { 5618c2ecf20Sopenharmony_ci printk("nvidiafb: Forcing display type to %s as " 5628c2ecf20Sopenharmony_ci "specified\n", par->FlatPanel ? "DFP" : "CRT"); 5638c2ecf20Sopenharmony_ci } 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci if (par->CRTCnumber == -1) { 5668c2ecf20Sopenharmony_ci if (CRTCnumber != -1) 5678c2ecf20Sopenharmony_ci par->CRTCnumber = CRTCnumber; 5688c2ecf20Sopenharmony_ci else { 5698c2ecf20Sopenharmony_ci printk("nvidiafb: Unable to detect which " 5708c2ecf20Sopenharmony_ci "CRTCNumber...\n"); 5718c2ecf20Sopenharmony_ci if (par->FlatPanel) 5728c2ecf20Sopenharmony_ci par->CRTCnumber = 1; 5738c2ecf20Sopenharmony_ci else 5748c2ecf20Sopenharmony_ci par->CRTCnumber = 0; 5758c2ecf20Sopenharmony_ci printk("...Defaulting to CRTCNumber %i\n", 5768c2ecf20Sopenharmony_ci par->CRTCnumber); 5778c2ecf20Sopenharmony_ci } 5788c2ecf20Sopenharmony_ci } else { 5798c2ecf20Sopenharmony_ci printk("nvidiafb: Forcing CRTCNumber %i as " 5808c2ecf20Sopenharmony_ci "specified\n", par->CRTCnumber); 5818c2ecf20Sopenharmony_ci } 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci if (monA) { 5848c2ecf20Sopenharmony_ci if (((monA->input & FB_DISP_DDI) && 5858c2ecf20Sopenharmony_ci par->FlatPanel) || 5868c2ecf20Sopenharmony_ci ((!(monA->input & FB_DISP_DDI)) && 5878c2ecf20Sopenharmony_ci !par->FlatPanel)) { 5888c2ecf20Sopenharmony_ci if (monB) { 5898c2ecf20Sopenharmony_ci fb_destroy_modedb(monB->modedb); 5908c2ecf20Sopenharmony_ci monB = NULL; 5918c2ecf20Sopenharmony_ci } 5928c2ecf20Sopenharmony_ci } else { 5938c2ecf20Sopenharmony_ci fb_destroy_modedb(monA->modedb); 5948c2ecf20Sopenharmony_ci monA = NULL; 5958c2ecf20Sopenharmony_ci } 5968c2ecf20Sopenharmony_ci } 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ci if (monB) { 5998c2ecf20Sopenharmony_ci if (((monB->input & FB_DISP_DDI) && 6008c2ecf20Sopenharmony_ci !par->FlatPanel) || 6018c2ecf20Sopenharmony_ci ((!(monB->input & FB_DISP_DDI)) && 6028c2ecf20Sopenharmony_ci par->FlatPanel)) { 6038c2ecf20Sopenharmony_ci fb_destroy_modedb(monB->modedb); 6048c2ecf20Sopenharmony_ci monB = NULL; 6058c2ecf20Sopenharmony_ci } else 6068c2ecf20Sopenharmony_ci monA = monB; 6078c2ecf20Sopenharmony_ci } 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci if (implementation == 0x0110) 6108c2ecf20Sopenharmony_ci cr44 = par->CRTCnumber * 0x3; 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci NV_WR32(par->PCRTC0, 0x00000860, oldhead); 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci VGA_WR08(par->PCIO, 0x03D4, 0x44); 6158c2ecf20Sopenharmony_ci VGA_WR08(par->PCIO, 0x03D5, cr44); 6168c2ecf20Sopenharmony_ci NVSelectHeadRegisters(par, par->CRTCnumber); 6178c2ecf20Sopenharmony_ci } 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci printk("nvidiafb: Using %s on CRTC %i\n", 6208c2ecf20Sopenharmony_ci par->FlatPanel ? (par->Television ? "TV" : "DFP") : "CRT", 6218c2ecf20Sopenharmony_ci par->CRTCnumber); 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ci if (par->FlatPanel && !par->Television) { 6248c2ecf20Sopenharmony_ci par->fpWidth = NV_RD32(par->PRAMDAC, 0x0820) + 1; 6258c2ecf20Sopenharmony_ci par->fpHeight = NV_RD32(par->PRAMDAC, 0x0800) + 1; 6268c2ecf20Sopenharmony_ci par->fpSyncs = NV_RD32(par->PRAMDAC, 0x0848) & 0x30000033; 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci printk("nvidiafb: Panel size is %i x %i\n", par->fpWidth, par->fpHeight); 6298c2ecf20Sopenharmony_ci } 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci if (monA) 6328c2ecf20Sopenharmony_ci info->monspecs = *monA; 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_ci if (!par->FlatPanel || !par->twoHeads) 6358c2ecf20Sopenharmony_ci par->FPDither = 0; 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_ci par->LVDS = 0; 6388c2ecf20Sopenharmony_ci if (par->FlatPanel && par->twoHeads) { 6398c2ecf20Sopenharmony_ci NV_WR32(par->PRAMDAC0, 0x08B0, 0x00010004); 6408c2ecf20Sopenharmony_ci if (NV_RD32(par->PRAMDAC0, 0x08b4) & 1) 6418c2ecf20Sopenharmony_ci par->LVDS = 1; 6428c2ecf20Sopenharmony_ci printk("nvidiafb: Panel is %s\n", par->LVDS ? "LVDS" : "TMDS"); 6438c2ecf20Sopenharmony_ci } 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci kfree(edidA); 6468c2ecf20Sopenharmony_ci kfree(edidB); 6478c2ecf20Sopenharmony_cidone: 6488c2ecf20Sopenharmony_ci kfree(var); 6498c2ecf20Sopenharmony_ci kfree(monitorA); 6508c2ecf20Sopenharmony_ci kfree(monitorB); 6518c2ecf20Sopenharmony_ci return err; 6528c2ecf20Sopenharmony_ci} 653