pm3_dac.c revision 4f6cd06f
1/* 2 * Copyright 2000,2001 by Sven Luther <luther@dpt-info.u-strasbg.fr>. 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that 7 * copyright notice and this permission notice appear in supporting 8 * documentation, and that the name of Sven Luther not be used in 9 * advertising or publicity pertaining to distribution of the software without 10 * specific, written prior permission. Sven Luther makes no representations 11 * about the suitability of this software for any purpose. It is provided 12 * "as is" without express or implied warranty. 13 * 14 * SVEN LUTHER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL SVEN LUTHER BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20 * PERFORMANCE OF THIS SOFTWARE. 21 * 22 * Authors: Sven Luther, <luther@dpt-info.u-strasbg.fr> 23 * Thomas Witzel, <twitzel@nmr.mgh.harvard.edu> 24 * Alan Hourihane, <alanh@fairlite.demon.co.uk> 25 * 26 * this work is sponsored by Appian Graphics. 27 * 28 */ 29/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/glint/pm3_dac.c,v 1.33tsi Exp $ */ 30 31#ifdef HAVE_CONFIG_H 32#include "config.h" 33#endif 34 35#include "xf86.h" 36#include "xf86_OSproc.h" 37 38#include "xf86PciInfo.h" 39#include "xf86Pci.h" 40#include "xf86int10.h" 41 42#include "glint_regs.h" 43#include "pm3_regs.h" 44#include "glint.h" 45 46#define DEBUG 0 47 48#if DEBUG 49# define TRACE_ENTER(str) ErrorF("glint: " str " %d\n",pScrn->scrnIndex) 50# define TRACE_EXIT(str) ErrorF("glint: " str " done\n") 51# define TRACE(str) ErrorF("glint trace: " str "\n") 52#else 53# define TRACE_ENTER(str) 54# define TRACE_EXIT(str) 55# define TRACE(str) 56#endif 57 58int 59Permedia3MemorySizeDetect(ScrnInfoPtr pScrn) 60{ 61 GLINTPtr pGlint = GLINTPTR (pScrn); 62 CARD32 size = 0, temp, temp1, temp2, i; 63 64 /* We can map 64MB, as that's the size of the Permedia3 aperture 65 * regardless of memory configuration */ 66 pGlint->FbMapSize = 64*1024*1024; 67 68#ifndef XSERVER_LIBPCIACCESS 69 /* Mark as VIDMEM_MMIO to avoid write-combining while detecting memory */ 70 pGlint->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 71 pGlint->PciTag, pGlint->FbAddress, pGlint->FbMapSize); 72#else 73 { 74 void** result = (void**)&pGlint->FbBase; 75 int err = pci_device_map_range(pGlint->PciInfo, 76 pGlint->FbAddress, 77 pGlint->FbMapSize, 78 PCI_DEV_MAP_FLAG_WRITABLE, 79 result); 80 81 if (err) 82 return FALSE; 83 } 84 85#endif 86 if (pGlint->FbBase == NULL) 87 return 0; 88 89 temp = GLINT_READ_REG(PM3MemBypassWriteMask); 90 GLINT_SLOW_WRITE_REG(0xffffffff, PM3MemBypassWriteMask); 91 92 /* The Permedia3 splits up memory, and even replicates it. Grrr. 93 * So that each 32MB appears at offset 0, and offset 32, unless 94 * there's really 64MB attached to the chip. 95 * So, 16MB appears at offset 0, nothing between 16-32, then it re-appears 96 * at offset 32. 97 * This below is to detect the cases of memory combinations 98 */ 99 100 /* Test first 32MB */ 101 for(i=0;i<32;i++) { 102 /* write test pattern */ 103 MMIO_OUT32(pGlint->FbBase, i*1024*1024, i*0x00345678); 104 mem_barrier(); 105 temp1 = MMIO_IN32(pGlint->FbBase, i*1024*1024); 106 /* Let's check for wrapover, write will fail at 16MB boundary */ 107 if (temp1 == (i*0x00345678)) 108 size = i; 109 else 110 break; 111 } 112 113 /* Ok, we're satisfied we've got 32MB, let's test the second lot */ 114 if ((size + 1) == i) { 115 for(i=0;i<32;i++) { 116 /* Clear first 32MB */ 117 MMIO_OUT32(pGlint->FbBase, i*1024*1024, 0); 118 mem_barrier(); 119 } 120 for(i=32;i<64;i++) { 121 /* write test pattern */ 122 MMIO_OUT32(pGlint->FbBase, i*1024*1024, i*0x00345678); 123 mem_barrier(); 124 temp1 = MMIO_IN32(pGlint->FbBase, i*1024*1024); 125 temp2 = MMIO_IN32(pGlint->FbBase, (i-32)*1024*1024); 126 /* Let's check for wrapover */ 127 if ( (temp1 == (i*0x00345678)) && (temp2 == 0) ) 128 size = i; 129 else 130 break; 131 } 132 } 133 134 GLINT_SLOW_WRITE_REG(temp, PM3MemBypassWriteMask); 135 136#ifndef XSERVER_LIBPCIACCESS 137 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pGlint->FbBase, 138 pGlint->FbMapSize); 139#else 140 pci_device_unmap_range(pGlint->PciInfo, pGlint->FbBase, pGlint->FbMapSize); 141#endif 142 143 pGlint->FbBase = NULL; 144 pGlint->FbMapSize = 0; 145 146 return ( (size+1) * 1024 ); 147} 148 149static unsigned long 150PM3DAC_CalculateClock 151( 152 unsigned long ReqClock, /* In kHz units */ 153 unsigned long RefClock, /* In kHz units */ 154 unsigned char *prescale, /* ClkPreScale */ 155 unsigned char *feedback, /* ClkFeedBackScale */ 156 unsigned char *postscale /* ClkPostScale */ 157 ) 158{ 159 unsigned long fMinVCO = 2000000; /* min fVCO is 200MHz (in 100Hz units) */ 160 unsigned long fMaxVCO = 6220000; /* max fVCO is 622MHz (in 100Hz units) */ 161 unsigned long fMinINTREF = 10000;/* min fINTREF is 1MHz (in 100Hz units) */ 162 unsigned long fMaxINTREF = 20000;/* max fINTREF is 2MHz (in 100Hz units) */ 163 unsigned long M, N, P; /* M=feedback, N=prescale, P=postscale */ 164 unsigned long fINTREF; 165 unsigned long fVCO; 166 unsigned long ActualClock; 167 long Error; 168 unsigned long LowestError = 1000000; 169 unsigned int bFoundFreq = FALSE; 170 int cInnerLoopIterations = 0; 171 int LoopCount; 172 unsigned long ClosestClock = 0; 173 174 ReqClock*=10; /* convert into 100Hz units */ 175 RefClock*=10; /* convert into 100Hz units */ 176 177 for(P = 0; P <= 5; ++P) 178 { 179 unsigned long fVCOLowest, fVCOHighest; 180 181 /* it is pointless going through the main loop if all values of 182 N produce an fVCO outside the acceptable range */ 183 N = 1; 184 M = (N * (1UL << P) * ReqClock) / (2 * RefClock); 185 fVCOLowest = (2 * RefClock * M) / N; 186 N = 255; 187 M = (N * (1UL << P) * ReqClock) / (2 * RefClock); 188 fVCOHighest = (2 * RefClock * M) / N; 189 190 if(fVCOHighest < fMinVCO || fVCOLowest > fMaxVCO) 191 { 192 continue; 193 } 194 195 for(N = 1; N <= 255; ++N, ++cInnerLoopIterations) 196 { 197 fINTREF = RefClock / N; 198 if(fINTREF < fMinINTREF || fINTREF > fMaxINTREF) 199 { 200 if(fINTREF > fMaxINTREF) 201 { 202 /* hopefully we will get into range as the prescale 203 value increases */ 204 continue; 205 } 206 else 207 { 208 /* already below minimum and it will only get worse: 209 move to the next postscale value */ 210 break; 211 } 212 } 213 214 M = (N * (1UL << P) * ReqClock) / (2 * RefClock); 215 if(M > 255) 216 { 217 /* M, N & P registers are only 8 bits wide */ 218 break; 219 } 220 221 /* we can expect rounding errors in calculating M, which 222 will always be rounded down. So we will checkout our 223 calculated value of M along with (M+1) */ 224 for(LoopCount = (M == 255) ? 1 : 2; --LoopCount >= 0; ++M) 225 { 226 fVCO = (2 * RefClock * M) / N; 227 if(fVCO >= fMinVCO && fVCO <= fMaxVCO) 228 { 229 ActualClock = fVCO / (1UL << P); 230 Error = ActualClock - ReqClock; 231 if(Error < 0) 232 Error = -Error; 233 if(Error < LowestError) 234 { 235 bFoundFreq = TRUE; 236 LowestError = Error; 237 ClosestClock = ActualClock; 238 *prescale = N; 239 *feedback = M; 240 *postscale = P; 241 if(Error == 0) 242 goto Done; 243 } 244 } 245 } 246 } 247 } 248 249Done: 250 251 if(bFoundFreq) 252 ActualClock = ClosestClock; 253 else 254 ActualClock = 0; 255 256#if 0 257 ErrorF("PM3DAC_CalculateClock: Got prescale=%d, feedback=%d, postscale=%d, WantedClock = %d00 ActualClock = %d00 (Error %d00)\n", 258 *prescale, *feedback, *postscale, ReqClock, ActualClock, LowestError); 259#endif 260 261 return(ActualClock); 262} 263 264static unsigned long 265PM4DAC_CalculateClock 266( 267 unsigned long req_clock, /* In kHz units */ 268 unsigned long ref_clock, /* In kHz units */ 269 unsigned char *param_m, /* ClkPreScale */ 270 unsigned char *param_n, /* ClkFeedBackScale */ 271 unsigned char *param_p /* ClkPostScale */ 272 ) 273{ 274#define INITIALFREQERR 10000 275 276 long fMinVCO = 200000; /* min fVCO is 200MHz (in 10000Hz units) */ 277 long fMaxVCO = 400000; /* max fVCO is 400MHz (in 10000Hz units) */ 278 unsigned long int M, N, P; 279 unsigned long int fVCO; 280 unsigned long int ActualClock; 281 int Error; 282 int LowestError = INITIALFREQERR; 283 short bFoundFreq = FALSE; 284 int cInnerLoopIterations = 0; 285 int LoopCount; 286 287 /* 288 * Actual Equations: 289 * fVCO = (ref_clock * M)/(N+1) 290 * PIXELCLOCK = fVCO/(1<<p) 291 * 200 <= fVCO <= 400 292 * 24 <= N <= 80 293 * 1 <= M <= 15 294 * 0 <= P <= 3 295 * 1Mhz < ref_clock/(N+1) <= 2Mhz - not used 296 * For refclk == 14.318 we have the tighter equations: 297 * 32 <= N <= 80 298 * 3 <= M <= 12 299 * Notes: 300 * The spec says that the PLLs will only do 260Mhz, but I have assumed 300Mhz 'cos 301 * 260Mhz is a crap limit. 302 */ 303 304#define P4RD_PLL_MIN_P 0 305#define P4RD_PLL_MAX_P 3 306#define P4RD_PLL_MIN_M 1 307#define P4RD_PLL_MAX_M 12 308#define P4RD_PLL_MIN_N 24 309#define P4RD_PLL_MAX_N 80 310 311 for(P = P4RD_PLL_MIN_P; P <= P4RD_PLL_MAX_P; ++P) { 312 unsigned long int fVCOLowest, fVCOHighest; 313 314 /* it's pointless going through the main loop if all values of 315 * N produce an fVCO outside the acceptable range */ 316 317 M = P4RD_PLL_MIN_M; 318 N = ((M + 1) * (1 << P) * req_clock) / ref_clock; 319 320 fVCOLowest = (ref_clock * N) / (M + 1); 321 322 M = P4RD_PLL_MAX_M; 323 N = ((M + 1) * (1 << P) * req_clock) / ref_clock; 324 325 fVCOHighest = (ref_clock * N) / (M + 1); 326 327 if(fVCOHighest < fMinVCO || fVCOLowest > fMaxVCO) 328 continue; 329 330 for(M = P4RD_PLL_MIN_M; M <= P4RD_PLL_MAX_M; ++M, ++cInnerLoopIterations) 331 { 332 N = ((M + 1) * (1 << P) * req_clock) / ref_clock; 333 334 if(N > P4RD_PLL_MAX_N || N < P4RD_PLL_MIN_N) 335 continue; 336 337 /* we can expect rounding errors in calculating M, which will always be rounded down. */ 338 /* So we'll checkout our calculated value of M along with (M+1) */ 339 340 for(LoopCount = (N == P4RD_PLL_MAX_N) ? 1 : 2; --LoopCount >= 0; ++N) 341 { 342 fVCO = (ref_clock * N) / (M + 1); 343 344 if( (fVCO >= fMinVCO) && (fVCO <= fMaxVCO) ) 345 { 346 ActualClock = (fVCO / (1 << P)); 347 348 Error = ActualClock - req_clock; 349 350 if(Error < 0) 351 Error = -Error; 352 353 /* It is desirable that we use the lowest value of M if the*/ 354 /* frequencies are the same.*/ 355 if(Error < LowestError || (Error == LowestError && M < *param_m)) 356 { 357 bFoundFreq = TRUE; 358 LowestError = Error; 359 *param_m = M; 360 *param_n = N; 361 *param_p = P; 362 if(Error == 0) 363 goto Done; 364 } 365 } 366 } 367 } 368 } 369 370Done: 371 if(bFoundFreq) 372 ActualClock = (ref_clock * (*param_n)) / (((*param_m) + 1) * (1 << (*param_p))); 373 else 374 ActualClock = 0; 375 376 return(ActualClock); 377} 378 379void 380Permedia3PreInit(ScrnInfoPtr pScrn) 381{ 382 GLINTPtr pGlint = GLINTPTR(pScrn); 383 CARD32 LocalMemCaps; 384 385 TRACE_ENTER("Permedia3PreInit"); 386 387 if (IS_J2000) { 388 unsigned char m,n,p; 389 390 if (pGlint->Chipset == PCI_VENDOR_3DLABS_CHIP_GAMMA) 391 GLINT_SLOW_WRITE_REG(GCSRSecondaryGLINTMapEn, GCSRAperture); 392 393 /* Memory timings for the Appian J2000 board. 394 * This is needed for the second head which is left un-initialized 395 * by the bios, thus freezing the machine. */ 396 GLINT_SLOW_WRITE_REG(0x02e311B8, PM3LocalMemCaps); 397 GLINT_SLOW_WRITE_REG(0x07424905, PM3LocalMemTimings); 398 GLINT_SLOW_WRITE_REG(0x0c000003, PM3LocalMemControl); 399 GLINT_SLOW_WRITE_REG(0x00000061, PM3LocalMemRefresh); 400 GLINT_SLOW_WRITE_REG(0x00000000, PM3LocalMemPowerDown); 401 402 /* Let's program the K, M and S Clocks to the same values as the bios 403 * does for first head : 404 * - KClk and MClk are 105Mhz. 405 * - S Clock is set to PClk. 406 * Note 1 : pGlint->RefClock is not set yet, so use 14318 instead. 407 * Note 2 : KClk gets internally halved, so we need to double it. 408 */ 409 (void) PM3DAC_CalculateClock(2*105000, 14318, &m,&n,&p); 410 Permedia2vOutIndReg(pScrn, PM3RD_KClkPreScale, 0x00, m); 411 Permedia2vOutIndReg(pScrn, PM3RD_KClkFeedbackScale, 0x00, n); 412 Permedia2vOutIndReg(pScrn, PM3RD_KClkPostScale, 0x00, p); 413 Permedia2vOutIndReg(pScrn, PM3RD_KClkControl, 0x00, 414 PM3RD_KClkControl_STATE_RUN | 415 PM3RD_KClkControl_SOURCE_PLL | 416 PM3RD_KClkControl_ENABLE); 417 Permedia2vOutIndReg(pScrn, PM3RD_MClkControl, 0x00, 418 PM3RD_MClkControl_STATE_RUN | 419 PM3RD_MClkControl_SOURCE_KCLK | 420 PM3RD_MClkControl_ENABLE); 421 Permedia2vOutIndReg(pScrn, PM3RD_SClkControl, 0x00, 422 PM3RD_SClkControl_STATE_RUN | 423 PM3RD_SClkControl_SOURCE_PCLK | 424 PM3RD_SClkControl_ENABLE); 425 } 426 427#if defined(__alpha__) 428 /* 429 * On Alpha, we have to "int10" secondary VX1 cards early; 430 * otherwise, some information taken from registers, like 431 * memory size, is incorrect. 432 */ 433 if (!xf86IsPrimaryPci(pGlint->PciInfo)) { 434 if ( IS_QVX1 ) { 435 436 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 437 "VX1 secondary enabling VGA before int10\n"); 438 439 /* Enable VGA on the current card. */ 440 PCI_WRITE_BYTE(pGlint->PciInfo, 0, 0xf8); 441 PCI_WRITE_BYTE(pGlint->PciInfo, 0, 0xf4); 442 PCI_WRITE_BYTE(pGlint->PciInfo, 0, 0xfc); 443 444 /* The card we are on should be VGA-enabled now, so run int10. */ 445 if (xf86LoadSubModule(pScrn, "int10")) { 446 xf86Int10InfoPtr pInt; 447 448 xf86LoaderReqSymLists(GLINTint10Symbols, NULL); 449 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initializing int10\n"); 450 pInt = xf86InitInt10(pGlint->pEnt->index); 451 xf86FreeInt10(pInt); 452 } 453 454 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 455 "VX1 secondary disabling VGA after int10\n"); 456 457 /* Finally, disable VGA on the current card. */ 458 PCI_WRITE_BYTE(pGlint->PciInfo, 0x70, 0xf8); 459 PCI_WRITE_BYTE(pGlint->PciInfo, 0x01, 0xf4); 460 PCI_WRITE_BYTE(pGlint->PciInfo, 0x00, 0xfc); 461 } 462 } 463#endif /* __alpha__ */ 464 465 /* If we have SDRAM instead of SGRAM, we have to do some things 466 differently in the FillRectSolid code. */ 467 LocalMemCaps = GLINT_READ_REG(PM3LocalMemCaps); 468 pGlint->PM3_UsingSGRAM = !(LocalMemCaps & PM3LocalMemCaps_NoWriteMask); 469 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using %s memory\n", 470 pGlint->PM3_UsingSGRAM ? "SGRAM" : "SDRAM"); 471 472 TRACE_EXIT("Permedia3PreInit"); 473} 474 475Bool 476Permedia3Init(ScrnInfoPtr pScrn, DisplayModePtr mode, GLINTRegPtr pReg) 477{ 478 GLINTPtr pGlint = GLINTPTR(pScrn); 479 CARD32 temp1, temp2, temp3, temp4; 480 481 if ((pGlint->numMultiDevices == 2) || (IS_J2000)) { 482 STOREREG(GCSRAperture, GCSRSecondaryGLINTMapEn); 483 } 484 485 if (pGlint->MultiAperture) { 486 STOREREG(GMultGLINTAperture, pGlint->realWidth); 487 STOREREG(GMultGLINT1, PCI_REGION_BASE(pGlint->MultiPciInfo[0], 2, REGION_MEM) & 0xFF800000); 488 STOREREG(GMultGLINT2, PCI_REGION_BASE(pGlint->MultiPciInfo[1], 2, REGION_MEM) & 0xFF800000); 489 } 490 491 STOREREG(PM3MemBypassWriteMask, 0xffffffff); 492 STOREREG(Aperture0, 0x00000000); 493 STOREREG(Aperture1, 0x00000000); 494 495 if (pGlint->Chipset == PCI_VENDOR_3DLABS_CHIP_GAMMA) 496 STOREREG(DFIFODis, 0x00000001); 497 498 STOREREG(FIFODis, 0x00000007); 499 500 temp1 = mode->CrtcHSyncStart - mode->CrtcHDisplay; 501 temp2 = mode->CrtcVSyncStart - mode->CrtcVDisplay; 502 temp3 = mode->CrtcHSyncEnd - mode->CrtcHSyncStart; 503 temp4 = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; 504 505 STOREREG(PMHTotal, Shiftbpp(pScrn, mode->CrtcHTotal - 1)); 506 STOREREG(PMHsEnd, Shiftbpp(pScrn, temp1 + temp3)); 507 STOREREG(PMHsStart, Shiftbpp(pScrn, temp1)); 508 STOREREG(PMHbEnd, Shiftbpp(pScrn, mode->CrtcHTotal - mode->CrtcHDisplay)); 509 STOREREG(PMHgEnd, Shiftbpp(pScrn, mode->CrtcHTotal - mode->CrtcHDisplay)); 510 STOREREG(PMScreenStride, Shiftbpp(pScrn, pScrn->displayWidth)); 511 512 STOREREG(PMVTotal, mode->CrtcVTotal - 1); 513 STOREREG(PMVsEnd, temp2 + temp4 - 1); 514 STOREREG(PMVsStart, temp2 - 1); 515 STOREREG(PMVbEnd, mode->CrtcVTotal - mode->CrtcVDisplay); 516 517 switch (pScrn->bitsPerPixel) 518 { 519 case 8: 520 STOREREG(PM3ByAperture1Mode, PM3ByApertureMode_PIXELSIZE_8BIT); 521 STOREREG(PM3ByAperture2Mode, PM3ByApertureMode_PIXELSIZE_8BIT); 522 STOREREG(PMVideoControl, 1 | (1 << 3) | (1 << 5) | (0 << 19)); 523 break; 524 case 16: 525#if X_BYTE_ORDER != X_BIG_ENDIAN 526 STOREREG(PM3ByAperture1Mode, PM3ByApertureMode_PIXELSIZE_16BIT); 527 STOREREG(PM3ByAperture2Mode, PM3ByApertureMode_PIXELSIZE_16BIT); 528#else 529 STOREREG(PM3ByAperture1Mode, PM3ByApertureMode_PIXELSIZE_16BIT | 530 PM3ByApertureMode_BYTESWAP_BADC); 531 STOREREG(PM3ByAperture2Mode, PM3ByApertureMode_PIXELSIZE_16BIT | 532 PM3ByApertureMode_BYTESWAP_BADC); 533#endif 534 STOREREG(PMVideoControl, 1 | (1 << 3) | (1 << 5) | (1 << 19)); 535 break; 536 case 32: 537#if X_BYTE_ORDER != X_BIG_ENDIAN 538 STOREREG(PM3ByAperture1Mode, PM3ByApertureMode_PIXELSIZE_32BIT); 539 STOREREG(PM3ByAperture2Mode, PM3ByApertureMode_PIXELSIZE_32BIT); 540#else 541 STOREREG(PM3ByAperture1Mode, PM3ByApertureMode_PIXELSIZE_32BIT | 542 PM3ByApertureMode_BYTESWAP_DCBA); 543 STOREREG(PM3ByAperture2Mode, PM3ByApertureMode_PIXELSIZE_32BIT | 544 PM3ByApertureMode_BYTESWAP_DCBA); 545#endif 546 STOREREG(PMVideoControl, 1 | (1 << 3) | (1 << 5) | (2 << 19)); 547 break; 548 } 549 550 STOREREG(VClkCtl, GLINT_READ_REG(VClkCtl) & 0xFFFFFFFC); 551 STOREREG(PMScreenBase, 0x00000000); 552 STOREREG(ChipConfig, GLINT_READ_REG(ChipConfig) & 0xFFFFFFFD); 553 554 { 555 /* Get the programmable clock values */ 556 unsigned char m,n,p; 557 558 /* Let's program the dot clock */ 559 switch (pGlint->Chipset) { 560 case PCI_VENDOR_3DLABS_CHIP_PERMEDIA4: 561 case PCI_VENDOR_3DLABS_CHIP_R4: 562 (void) PM4DAC_CalculateClock(mode->Clock, pGlint->RefClock, &m,&n,&p); 563 break; 564 case PCI_VENDOR_3DLABS_CHIP_PERMEDIA3: 565 (void) PM3DAC_CalculateClock(mode->Clock, pGlint->RefClock, &m,&n,&p); 566 break; 567 case PCI_VENDOR_3DLABS_CHIP_GAMMA: 568 switch (pGlint->MultiChip) { 569 case PCI_CHIP_PERMEDIA3: 570 (void) PM3DAC_CalculateClock(mode->Clock, 571 pGlint->RefClock, &m,&n,&p); 572 break; 573 case PCI_CHIP_R4: 574 (void) PM4DAC_CalculateClock(mode->Clock, 575 pGlint->RefClock, &m,&n,&p); 576 break; 577 } 578 break; 579 } 580 STOREDAC(PM3RD_DClk0PreScale, m); 581 STOREDAC(PM3RD_DClk0FeedbackScale, n); 582 STOREDAC(PM3RD_DClk0PostScale, p); 583 } 584 585 temp1 = 0; 586 temp2 = 0; 587 temp3 = 0; 588 589 if (pGlint->UseFlatPanel) { 590 temp2 |= PM3RD_DACControl_BLANK_PEDESTAL_ENABLE; 591 temp3 |= PM3RD_MiscControl_VSB_OUTPUT_ENABLE; 592 STOREREG(VSConfiguration, 0x06); 593 STOREREG(VSBBase, 1<<14); 594 } 595 596 if (mode->Flags & V_PHSYNC) temp1 |= PM3RD_SyncControl_HSYNC_ACTIVE_HIGH; 597 if (mode->Flags & V_PVSYNC) temp1 |= PM3RD_SyncControl_VSYNC_ACTIVE_HIGH; 598 599 STOREREG(PM2VDACRDIndexControl, 0x00); 600 STOREDAC(PM2VDACRDSyncControl, temp1); 601 STOREDAC(PM2VDACRDDACControl, temp2); 602 603 if (pScrn->rgbBits == 8) 604 temp3 |= 0x01; /* 8bit DAC */ 605 606 switch (pScrn->bitsPerPixel) 607 { 608 case 8: 609 STOREDAC(PM2VDACRDPixelSize, 0x00); 610 STOREDAC(PM2VDACRDColorFormat, 0x2E); 611 break; 612 case 16: 613 temp3 |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE; 614 STOREDAC(PM2VDACRDPixelSize, 0x01); 615 if (pScrn->depth == 15) { 616 STOREDAC(PM2VDACRDColorFormat, 0x61); 617 } else { 618 STOREDAC(PM2VDACRDColorFormat, 0x70); 619 } 620 break; 621 case 24: 622 temp3 |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE; 623 STOREDAC(PM2VDACRDPixelSize, 0x04); 624 STOREDAC(PM2VDACRDColorFormat, 0x20); 625 break; 626 case 32: 627 temp3 |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE; 628 if (pScrn->overlayFlags & OVERLAY_8_32_PLANAR) { 629 temp3 |= 0x18; 630 STOREDAC(PM2VDACRDOverlayKey, pScrn->colorKey); 631 } 632 STOREDAC(PM2VDACRDPixelSize, 0x02); 633 STOREDAC(PM2VDACRDColorFormat, 0x20); 634 break; 635 } 636 STOREDAC(PM2VDACRDMiscControl, temp3); 637 638 STOREREG(PM3FifoControl, 0x905); /* Lower the default fifo threshold */ 639 640 return(TRUE); 641} 642 643void 644Permedia3Save(ScrnInfoPtr pScrn, GLINTRegPtr pReg) 645{ 646 GLINTPtr pGlint = GLINTPTR(pScrn); 647 int i; 648 649 /* We can't rely on the vgahw layer copying the font information 650 * back properly, due to problems with MMIO access to VGA space 651 * so we memcpy the information using the slow routines */ 652 xf86SlowBcopy((CARD8*)pGlint->FbBase, (CARD8*)pGlint->VGAdata, 65536); 653 654 if ((pGlint->numMultiDevices == 2) || (IS_J2000)) { 655 SAVEREG(GCSRAperture); 656 } 657 658 if (pGlint->MultiAperture) { 659 SAVEREG(GMultGLINTAperture); 660 SAVEREG(GMultGLINT1); 661 SAVEREG(GMultGLINT2); 662 } 663 664 /* Permedia 3 memory Timings */ 665 SAVEREG(PM3MemBypassWriteMask); 666 SAVEREG(PM3ByAperture1Mode); 667 SAVEREG(PM3ByAperture2Mode); 668 SAVEREG(ChipConfig); 669 SAVEREG(Aperture0); 670 SAVEREG(Aperture1); 671 SAVEREG(PM3FifoControl); 672 673 if (pGlint->Chipset == PCI_VENDOR_3DLABS_CHIP_GAMMA) 674 SAVEREG(DFIFODis); 675 SAVEREG(FIFODis); 676 SAVEREG(PMHTotal); 677 SAVEREG(PMHbEnd); 678 SAVEREG(PMHgEnd); 679 SAVEREG(PMScreenStride); 680 SAVEREG(PMHsStart); 681 SAVEREG(PMHsEnd); 682 SAVEREG(PMVTotal); 683 SAVEREG(PMVbEnd); 684 SAVEREG(PMVsStart); 685 SAVEREG(PMVsEnd); 686 SAVEREG(PMScreenBase); 687 SAVEREG(PMVideoControl); 688 SAVEREG(VClkCtl); 689 if (pGlint->UseFlatPanel) { 690 SAVEREG(VSConfiguration); 691 SAVEREG(VSBBase); 692 } 693 694 for (i=0;i<768;i++) { 695 Permedia2ReadAddress(pScrn, i); 696 pReg->cmap[i] = Permedia2ReadData(pScrn); 697 } 698 699 SAVEREG(PM2VDACRDIndexControl); 700 P2VIN(PM2VDACRDOverlayKey); 701 P2VIN(PM2VDACRDSyncControl); 702 P2VIN(PM2VDACRDMiscControl); 703 P2VIN(PM2VDACRDDACControl); 704 P2VIN(PM2VDACRDPixelSize); 705 P2VIN(PM2VDACRDColorFormat); 706 P2VIN(PM2VDACRDDClk0PreScale); 707 P2VIN(PM2VDACRDDClk0FeedbackScale); 708 P2VIN(PM2VDACRDDClk0PostScale); 709} 710 711void 712Permedia3Restore(ScrnInfoPtr pScrn, GLINTRegPtr pReg) 713{ 714 GLINTPtr pGlint = GLINTPTR(pScrn); 715 CARD32 temp; 716 int i; 717 718 /* We can't rely on the vgahw layer copying the font information 719 * back properly, due to problems with MMIO access to VGA space 720 * so we memcpy the information using the slow routines */ 721 if (pGlint->STATE) 722 xf86SlowBcopy((CARD8*)pGlint->VGAdata, (CARD8*)pGlint->FbBase, 65536); 723 724 if ((pGlint->numMultiDevices == 2) || (IS_J2000)) { 725 RESTOREREG(GCSRAperture); 726 } 727 728 if (pGlint->MultiAperture) { 729 RESTOREREG(GMultGLINTAperture); 730 RESTOREREG(GMultGLINT1); 731 RESTOREREG(GMultGLINT2); 732 } 733 734 /* Permedia 3 memory Timings */ 735 RESTOREREG(PM3MemBypassWriteMask); 736 RESTOREREG(PM3ByAperture1Mode); 737 RESTOREREG(PM3ByAperture2Mode); 738 RESTOREREG(ChipConfig); 739 RESTOREREG(Aperture0); 740 RESTOREREG(Aperture1); 741 RESTOREREG(PM3FifoControl); 742 if (pGlint->Chipset == PCI_VENDOR_3DLABS_CHIP_GAMMA) 743 RESTOREREG(DFIFODis); 744 RESTOREREG(FIFODis); 745 RESTOREREG(PMVideoControl); 746 RESTOREREG(PMHbEnd); 747 RESTOREREG(PMHgEnd); 748 RESTOREREG(PMScreenBase); 749 RESTOREREG(VClkCtl); 750 RESTOREREG(PMScreenStride); 751 RESTOREREG(PMHTotal); 752 RESTOREREG(PMHsStart); 753 RESTOREREG(PMHsEnd); 754 RESTOREREG(PMVTotal); 755 RESTOREREG(PMVbEnd); 756 RESTOREREG(PMVsStart); 757 RESTOREREG(PMVsEnd); 758 759 if (pGlint->UseFlatPanel) { 760 RESTOREREG(VSConfiguration); 761 RESTOREREG(VSBBase); 762 } 763 764 RESTOREREG(PM2VDACRDIndexControl); 765 P2VOUT(PM2VDACRDOverlayKey); 766 P2VOUT(PM2VDACRDSyncControl); 767 P2VOUT(PM2VDACRDMiscControl); 768 P2VOUT(PM2VDACRDDACControl); 769 P2VOUT(PM2VDACRDPixelSize); 770 P2VOUT(PM2VDACRDColorFormat); 771 772 for (i=0;i<768;i++) { 773 Permedia2WriteAddress(pScrn, i); 774 Permedia2WriteData(pScrn, pReg->cmap[i]); 775 } 776 777 temp = Permedia2vInIndReg(pScrn, PM2VDACIndexClockControl) & 0xFC; 778 P2VOUT(PM2VDACRDDClk0PreScale); 779 P2VOUT(PM2VDACRDDClk0FeedbackScale); 780 P2VOUT(PM2VDACRDDClk0PostScale); 781 Permedia2vOutIndReg(pScrn, PM2VDACIndexClockControl, 0x00, temp|0x03); 782} 783 784void Permedia3LoadPalette( 785 ScrnInfoPtr pScrn, 786 int numColors, 787 int *indices, 788 LOCO *colors, 789 VisualPtr pVisual 790){ 791#if 0 792 GLINTPtr pGlint = GLINTPTR(pScrn); 793#endif 794 int i, index, shift = 0, j, repeat = 1; 795 796 if (pScrn->depth == 15) { 797 repeat = 8; 798 shift = 3; 799 } 800 801 for(i = 0; i < numColors; i++) { 802 index = indices[i]; 803 for (j = 0; j < repeat; j++) { 804 Permedia2WriteAddress(pScrn, (index << shift)+j); 805 Permedia2WriteData(pScrn, colors[index].red); 806 Permedia2WriteData(pScrn, colors[index].green); 807 Permedia2WriteData(pScrn, colors[index].blue); 808 } 809#if 0 810 GLINT_SLOW_WRITE_REG(index, PM3LUTIndex); 811 GLINT_SLOW_WRITE_REG((colors[index].red & 0xFF) | 812 ((colors[index].green & 0xFF) << 8) | 813 ((colors[index].blue & 0xFF) << 16), 814 PM3LUTData); 815#endif 816 } 817} 818 819/* special one for 565 mode */ 820void Permedia3LoadPalette16( 821 ScrnInfoPtr pScrn, 822 int numColors, 823 int *indices, 824 LOCO *colors, 825 VisualPtr pVisual 826){ 827#if 0 828 GLINTPtr pGlint = GLINTPTR(pScrn); 829#endif 830 int i, index, j; 831 832 for(i = 0; i < numColors; i++) { 833 index = indices[i]; 834 for (j = 0; j < 4; j++) { 835 Permedia2WriteAddress(pScrn, (index << 2)+j); 836 Permedia2WriteData(pScrn, colors[index >> 1].red); 837 Permedia2WriteData(pScrn, colors[index].green); 838 Permedia2WriteData(pScrn, colors[index >> 1].blue); 839 } 840#if 0 841 GLINT_SLOW_WRITE_REG(index, PM3LUTIndex); 842 GLINT_SLOW_WRITE_REG((colors[index].red & 0xFF) | 843 ((colors[index].green & 0xFF) << 8) | 844 ((colors[index].blue & 0xFF) << 16), 845 PM3LUTData); 846#endif 847 848 if(index <= 31) { 849 for (j = 0; j < 4; j++) { 850 Permedia2WriteAddress(pScrn, (index << 3)+j); 851 Permedia2WriteData(pScrn, colors[index].red); 852 Permedia2WriteData(pScrn, colors[(index << 1) + 1].green); 853 Permedia2WriteData(pScrn, colors[index].blue); 854 } 855 } 856 } 857} 858