1/* $XConsortium: nv_driver.c /main/3 1996/10/28 05:13:37 kaleb $ */ 2/* 3 * Copyright 1996-1997 David J. McKay 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * DAVID J. MCKAY BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 19 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 20 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * SOFTWARE. 22 */ 23 24/* 25 * GPL licensing note -- nVidia is allowing a liberal interpretation of 26 * the documentation restriction above, to merely say that this nVidia's 27 * copyright and disclaimer should be included with all code derived 28 * from this source. -- Jeff Garzik <jgarzik@pobox.com>, 01/Nov/99 29 */ 30 31/* Hacked together from mga driver and 3.3.4 NVIDIA driver by Jarno Paananen 32 <jpaana@s2.org> */ 33 34/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_setup.c,v 1.18 2002/08/0 355 20:47:06 mvojkovi Exp $ */ 36 37#include <linux/delay.h> 38#include <linux/pci.h> 39#include <linux/pci_ids.h> 40#include "nv_type.h" 41#include "rivafb.h" 42#include "nvreg.h" 43 44#define PFX "rivafb: " 45 46static inline unsigned char MISCin(struct riva_par *par) 47{ 48 return (VGA_RD08(par->riva.PVIO, 0x3cc)); 49} 50 51static Bool 52riva_is_connected(struct riva_par *par, Bool second) 53{ 54 volatile U032 __iomem *PRAMDAC = par->riva.PRAMDAC0; 55 U032 reg52C, reg608; 56 Bool present; 57 58 if(second) PRAMDAC += 0x800; 59 60 reg52C = NV_RD32(PRAMDAC, 0x052C); 61 reg608 = NV_RD32(PRAMDAC, 0x0608); 62 63 NV_WR32(PRAMDAC, 0x0608, reg608 & ~0x00010000); 64 65 NV_WR32(PRAMDAC, 0x052C, reg52C & 0x0000FEEE); 66 mdelay(1); 67 NV_WR32(PRAMDAC, 0x052C, NV_RD32(PRAMDAC, 0x052C) | 1); 68 69 NV_WR32(par->riva.PRAMDAC0, 0x0610, 0x94050140); 70 NV_WR32(par->riva.PRAMDAC0, 0x0608, 0x00001000); 71 72 mdelay(1); 73 74 present = (NV_RD32(PRAMDAC, 0x0608) & (1 << 28)) ? TRUE : FALSE; 75 76 NV_WR32(par->riva.PRAMDAC0, 0x0608, 77 NV_RD32(par->riva.PRAMDAC0, 0x0608) & 0x0000EFFF); 78 79 NV_WR32(PRAMDAC, 0x052C, reg52C); 80 NV_WR32(PRAMDAC, 0x0608, reg608); 81 82 return present; 83} 84 85static void 86riva_override_CRTC(struct riva_par *par) 87{ 88 printk(KERN_INFO PFX 89 "Detected CRTC controller %i being used\n", 90 par->SecondCRTC ? 1 : 0); 91 92 if(par->forceCRTC != -1) { 93 printk(KERN_INFO PFX 94 "Forcing usage of CRTC %i\n", par->forceCRTC); 95 par->SecondCRTC = par->forceCRTC; 96 } 97} 98 99static void 100riva_is_second(struct riva_par *par) 101{ 102 if (par->FlatPanel == 1) { 103 switch(par->Chipset & 0xffff) { 104 case 0x0174: 105 case 0x0175: 106 case 0x0176: 107 case 0x0177: 108 case 0x0179: 109 case 0x017C: 110 case 0x017D: 111 case 0x0186: 112 case 0x0187: 113 /* this might not be a good default for the chips below */ 114 case 0x0286: 115 case 0x028C: 116 case 0x0316: 117 case 0x0317: 118 case 0x031A: 119 case 0x031B: 120 case 0x031C: 121 case 0x031D: 122 case 0x031E: 123 case 0x031F: 124 case 0x0324: 125 case 0x0325: 126 case 0x0328: 127 case 0x0329: 128 case 0x032C: 129 case 0x032D: 130 par->SecondCRTC = TRUE; 131 break; 132 default: 133 par->SecondCRTC = FALSE; 134 break; 135 } 136 } else { 137 if(riva_is_connected(par, 0)) { 138 139 if (NV_RD32(par->riva.PRAMDAC0, 0x0000052C) & 0x100) 140 par->SecondCRTC = TRUE; 141 else 142 par->SecondCRTC = FALSE; 143 } else 144 if (riva_is_connected(par, 1)) { 145 if(NV_RD32(par->riva.PRAMDAC0, 0x0000252C) & 0x100) 146 par->SecondCRTC = TRUE; 147 else 148 par->SecondCRTC = FALSE; 149 } else /* default */ 150 par->SecondCRTC = FALSE; 151 } 152 riva_override_CRTC(par); 153} 154 155unsigned long riva_get_memlen(struct riva_par *par) 156{ 157 RIVA_HW_INST *chip = &par->riva; 158 unsigned long memlen = 0; 159 unsigned int chipset = par->Chipset; 160 struct pci_dev* dev; 161 u32 amt; 162 163 switch (chip->Architecture) { 164 case NV_ARCH_03: 165 if (NV_RD32(chip->PFB, 0x00000000) & 0x00000020) { 166 if (((NV_RD32(chip->PMC, 0x00000000) & 0xF0) == 0x20) 167 && ((NV_RD32(chip->PMC, 0x00000000)&0x0F)>=0x02)) { 168 /* 169 * SDRAM 128 ZX. 170 */ 171 switch (NV_RD32(chip->PFB,0x00000000) & 0x03) { 172 case 2: 173 memlen = 1024 * 4; 174 break; 175 case 1: 176 memlen = 1024 * 2; 177 break; 178 default: 179 memlen = 1024 * 8; 180 break; 181 } 182 } else { 183 memlen = 1024 * 8; 184 } 185 } else { 186 /* 187 * SGRAM 128. 188 */ 189 switch (NV_RD32(chip->PFB, 0x00000000) & 0x00000003) { 190 case 0: 191 memlen = 1024 * 8; 192 break; 193 case 2: 194 memlen = 1024 * 4; 195 break; 196 default: 197 memlen = 1024 * 2; 198 break; 199 } 200 } 201 break; 202 case NV_ARCH_04: 203 if (NV_RD32(chip->PFB, 0x00000000) & 0x00000100) { 204 memlen = ((NV_RD32(chip->PFB, 0x00000000)>>12)&0x0F) * 205 1024 * 2 + 1024 * 2; 206 } else { 207 switch (NV_RD32(chip->PFB, 0x00000000) & 0x00000003) { 208 case 0: 209 memlen = 1024 * 32; 210 break; 211 case 1: 212 memlen = 1024 * 4; 213 break; 214 case 2: 215 memlen = 1024 * 8; 216 break; 217 case 3: 218 default: 219 memlen = 1024 * 16; 220 break; 221 } 222 } 223 break; 224 case NV_ARCH_10: 225 case NV_ARCH_20: 226 case NV_ARCH_30: 227 if(chipset == NV_CHIP_IGEFORCE2) { 228 229 dev = pci_get_bus_and_slot(0, 1); 230 pci_read_config_dword(dev, 0x7C, &amt); 231 pci_dev_put(dev); 232 memlen = (((amt >> 6) & 31) + 1) * 1024; 233 } else if (chipset == NV_CHIP_0x01F0) { 234 dev = pci_get_bus_and_slot(0, 1); 235 pci_read_config_dword(dev, 0x84, &amt); 236 pci_dev_put(dev); 237 memlen = (((amt >> 4) & 127) + 1) * 1024; 238 } else { 239 switch ((NV_RD32(chip->PFB, 0x0000020C) >> 20) & 240 0x000000FF){ 241 case 0x02: 242 memlen = 1024 * 2; 243 break; 244 case 0x04: 245 memlen = 1024 * 4; 246 break; 247 case 0x08: 248 memlen = 1024 * 8; 249 break; 250 case 0x10: 251 memlen = 1024 * 16; 252 break; 253 case 0x20: 254 memlen = 1024 * 32; 255 break; 256 case 0x40: 257 memlen = 1024 * 64; 258 break; 259 case 0x80: 260 memlen = 1024 * 128; 261 break; 262 default: 263 memlen = 1024 * 16; 264 break; 265 } 266 } 267 break; 268 } 269 return memlen; 270} 271 272unsigned long riva_get_maxdclk(struct riva_par *par) 273{ 274 RIVA_HW_INST *chip = &par->riva; 275 unsigned long dclk = 0; 276 277 switch (chip->Architecture) { 278 case NV_ARCH_03: 279 if (NV_RD32(chip->PFB, 0x00000000) & 0x00000020) { 280 if (((NV_RD32(chip->PMC, 0x00000000) & 0xF0) == 0x20) 281 && ((NV_RD32(chip->PMC,0x00000000)&0x0F) >= 0x02)) { 282 /* 283 * SDRAM 128 ZX. 284 */ 285 dclk = 800000; 286 } else { 287 dclk = 1000000; 288 } 289 } else { 290 /* 291 * SGRAM 128. 292 */ 293 dclk = 1000000; 294 } 295 break; 296 case NV_ARCH_04: 297 case NV_ARCH_10: 298 case NV_ARCH_20: 299 case NV_ARCH_30: 300 switch ((NV_RD32(chip->PFB, 0x00000000) >> 3) & 0x00000003) { 301 case 3: 302 dclk = 800000; 303 break; 304 default: 305 dclk = 1000000; 306 break; 307 } 308 break; 309 } 310 return dclk; 311} 312 313void 314riva_common_setup(struct riva_par *par) 315{ 316 par->riva.EnableIRQ = 0; 317 par->riva.PRAMDAC0 = 318 (volatile U032 __iomem *)(par->ctrl_base + 0x00680000); 319 par->riva.PFB = 320 (volatile U032 __iomem *)(par->ctrl_base + 0x00100000); 321 par->riva.PFIFO = 322 (volatile U032 __iomem *)(par->ctrl_base + 0x00002000); 323 par->riva.PGRAPH = 324 (volatile U032 __iomem *)(par->ctrl_base + 0x00400000); 325 par->riva.PEXTDEV = 326 (volatile U032 __iomem *)(par->ctrl_base + 0x00101000); 327 par->riva.PTIMER = 328 (volatile U032 __iomem *)(par->ctrl_base + 0x00009000); 329 par->riva.PMC = 330 (volatile U032 __iomem *)(par->ctrl_base + 0x00000000); 331 par->riva.FIFO = 332 (volatile U032 __iomem *)(par->ctrl_base + 0x00800000); 333 par->riva.PCIO0 = par->ctrl_base + 0x00601000; 334 par->riva.PDIO0 = par->ctrl_base + 0x00681000; 335 par->riva.PVIO = par->ctrl_base + 0x000C0000; 336 337 par->riva.IO = (MISCin(par) & 0x01) ? 0x3D0 : 0x3B0; 338 339 if (par->FlatPanel == -1) { 340 switch (par->Chipset & 0xffff) { 341 case 0x0112: /* known laptop chips */ 342 case 0x0174: 343 case 0x0175: 344 case 0x0176: 345 case 0x0177: 346 case 0x0179: 347 case 0x017C: 348 case 0x017D: 349 case 0x0186: 350 case 0x0187: 351 case 0x0286: 352 case 0x028C: 353 case 0x0316: 354 case 0x0317: 355 case 0x031A: 356 case 0x031B: 357 case 0x031C: 358 case 0x031D: 359 case 0x031E: 360 case 0x031F: 361 case 0x0324: 362 case 0x0325: 363 case 0x0328: 364 case 0x0329: 365 case 0x032C: 366 case 0x032D: 367 printk(KERN_INFO PFX 368 "On a laptop. Assuming Digital Flat Panel\n"); 369 par->FlatPanel = 1; 370 break; 371 default: 372 break; 373 } 374 } 375 376 switch (par->Chipset & 0x0ff0) { 377 case 0x0110: 378 if (par->Chipset == NV_CHIP_GEFORCE2_GO) 379 par->SecondCRTC = TRUE; 380#if defined(__powerpc__) 381 if (par->FlatPanel == 1) 382 par->SecondCRTC = TRUE; 383#endif 384 riva_override_CRTC(par); 385 break; 386 case 0x0170: 387 case 0x0180: 388 case 0x01F0: 389 case 0x0250: 390 case 0x0280: 391 case 0x0300: 392 case 0x0310: 393 case 0x0320: 394 case 0x0330: 395 case 0x0340: 396 riva_is_second(par); 397 break; 398 default: 399 break; 400 } 401 402 if (par->SecondCRTC) { 403 par->riva.PCIO = par->riva.PCIO0 + 0x2000; 404 par->riva.PCRTC = par->riva.PCRTC0 + 0x800; 405 par->riva.PRAMDAC = par->riva.PRAMDAC0 + 0x800; 406 par->riva.PDIO = par->riva.PDIO0 + 0x2000; 407 } else { 408 par->riva.PCIO = par->riva.PCIO0; 409 par->riva.PCRTC = par->riva.PCRTC0; 410 par->riva.PRAMDAC = par->riva.PRAMDAC0; 411 par->riva.PDIO = par->riva.PDIO0; 412 } 413 414 if (par->FlatPanel == -1) { 415 /* Fix me, need x86 DDC code */ 416 par->FlatPanel = 0; 417 } 418 par->riva.flatPanel = (par->FlatPanel > 0) ? TRUE : FALSE; 419 420 RivaGetConfig(&par->riva, par->Chipset); 421} 422 423