mga_dacG.c revision a31a186a
1fe5e51b7Smrg/* 2fe5e51b7Smrg * MGA-1064, MGA-G100, MGA-G200, MGA-G400, MGA-G550 RAMDAC driver 3fe5e51b7Smrg */ 4fe5e51b7Smrg 5fe5e51b7Smrg#ifdef HAVE_CONFIG_H 6fe5e51b7Smrg#include "config.h" 7fe5e51b7Smrg#endif 8fe5e51b7Smrg 9fe5e51b7Smrg#include "colormapst.h" 10fe5e51b7Smrg 11fe5e51b7Smrg/* All drivers should typically include these */ 12fe5e51b7Smrg#include "xf86.h" 13fe5e51b7Smrg#include "xf86_OSproc.h" 14fe5e51b7Smrg 15fe5e51b7Smrg/* Drivers for PCI hardware need this */ 16fe5e51b7Smrg#include "xf86PciInfo.h" 17fe5e51b7Smrg 18fe5e51b7Smrg/* Drivers that need to access the PCI config space directly need this */ 19fe5e51b7Smrg#include "xf86Pci.h" 20fe5e51b7Smrg 21fe5e51b7Smrg#include "mga_reg.h" 22fe5e51b7Smrg#include "mga.h" 23fe5e51b7Smrg#include "mga_macros.h" 24fe5e51b7Smrg#include "mga_maven.h" 25fe5e51b7Smrg 26fe5e51b7Smrg#include "xf86DDC.h" 27fe5e51b7Smrg 28fe5e51b7Smrg#include <stdlib.h> 29fe5e51b7Smrg#include <unistd.h> 30fe5e51b7Smrg 31fe5e51b7Smrg/* 32fe5e51b7Smrg * implementation 33fe5e51b7Smrg */ 34fe5e51b7Smrg 35fe5e51b7Smrg#define DACREGSIZE 0x50 36fe5e51b7Smrg 37fe5e51b7Smrg/* 38fe5e51b7Smrg * Only change bits shown in this mask. Ideally reserved bits should be 39fe5e51b7Smrg * zeroed here. Also, don't change the vgaioen bit here since it is 40fe5e51b7Smrg * controlled elsewhere. 41fe5e51b7Smrg * 42fe5e51b7Smrg * XXX These settings need to be checked. 43fe5e51b7Smrg */ 44fe5e51b7Smrg#define OPTION1_MASK 0xFFFFFEFF 45fe5e51b7Smrg#define OPTION2_MASK 0xFFFFFFFF 46fe5e51b7Smrg#define OPTION3_MASK 0xFFFFFFFF 47fe5e51b7Smrg 48fe5e51b7Smrg#define OPTION1_MASK_PRIMARY 0xFFFC0FF 49fe5e51b7Smrg 50fe5e51b7Smrgstatic void MGAGRamdacInit(ScrnInfoPtr); 51fe5e51b7Smrgstatic void MGAGSave(ScrnInfoPtr, vgaRegPtr, MGARegPtr, Bool); 52fe5e51b7Smrgstatic void MGAGRestore(ScrnInfoPtr, vgaRegPtr, MGARegPtr, Bool); 53fe5e51b7Smrgstatic Bool MGAGInit(ScrnInfoPtr, DisplayModePtr); 54fe5e51b7Smrgstatic void MGAGLoadPalette(ScrnInfoPtr, int, int*, LOCO*, VisualPtr); 55fe5e51b7Smrgstatic Bool MGAG_i2cInit(ScrnInfoPtr pScrn); 56fe5e51b7Smrg 57fe5e51b7Smrgstatic void 58fe5e51b7SmrgMGAG200SEComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *M, int *N, int *P) 59fe5e51b7Smrg{ 60fe5e51b7Smrg unsigned int ulComputedFo; 61fe5e51b7Smrg unsigned int ulFDelta; 62fe5e51b7Smrg unsigned int ulFPermitedDelta; 63fe5e51b7Smrg unsigned int ulFTmpDelta; 64fe5e51b7Smrg unsigned int ulVCOMax, ulVCOMin; 65fe5e51b7Smrg unsigned int ulTestP; 66fe5e51b7Smrg unsigned int ulTestM; 67fe5e51b7Smrg unsigned int ulTestN; 68fe5e51b7Smrg unsigned int ulPLLFreqRef; 69fe5e51b7Smrg 70fe5e51b7Smrg ulVCOMax = 320000; 71fe5e51b7Smrg ulVCOMin = 160000; 72fe5e51b7Smrg ulPLLFreqRef = 25000; 73fe5e51b7Smrg 74fe5e51b7Smrg ulFDelta = 0xFFFFFFFF; 75fe5e51b7Smrg /* Permited delta is 0.5% as VESA Specification */ 76fe5e51b7Smrg ulFPermitedDelta = lFo * 5 / 1000; 77fe5e51b7Smrg 78fe5e51b7Smrg /* Then we need to minimize the M while staying within 0.5% */ 79fe5e51b7Smrg for (ulTestP = 8; ulTestP > 0; ulTestP >>= 1) { 80eda3803bSmrg if ((lFo * ulTestP) > ulVCOMax) continue; 81eda3803bSmrg if ((lFo * ulTestP) < ulVCOMin) continue; 82eda3803bSmrg 83eda3803bSmrg for (ulTestN = 17; ulTestN <= 256; ulTestN++) { 84eda3803bSmrg for (ulTestM = 1; ulTestM <= 32; ulTestM++) { 85eda3803bSmrg ulComputedFo = (ulPLLFreqRef * ulTestN) / (ulTestM * ulTestP); 86eda3803bSmrg if (ulComputedFo > lFo) 87eda3803bSmrg ulFTmpDelta = ulComputedFo - lFo; 88eda3803bSmrg else 89eda3803bSmrg ulFTmpDelta = lFo - ulComputedFo; 90eda3803bSmrg 91eda3803bSmrg if (ulFTmpDelta < ulFDelta) { 92eda3803bSmrg ulFDelta = ulFTmpDelta; 93eda3803bSmrg *M = ulTestM - 1; 94eda3803bSmrg *N = ulTestN - 1; 95eda3803bSmrg *P = ulTestP - 1; 96eda3803bSmrg } 97eda3803bSmrg } 98eda3803bSmrg } 99eda3803bSmrg } 100eda3803bSmrg} 101eda3803bSmrg 102eda3803bSmrgstatic void 103eda3803bSmrgMGAG200EVComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *M, int *N, int *P) 104eda3803bSmrg{ 105eda3803bSmrg unsigned int ulComputedFo; 106eda3803bSmrg unsigned int ulFDelta; 107eda3803bSmrg unsigned int ulFPermitedDelta; 108eda3803bSmrg unsigned int ulFTmpDelta; 109eda3803bSmrg unsigned int ulTestP; 110eda3803bSmrg unsigned int ulTestM; 111eda3803bSmrg unsigned int ulTestN; 112eda3803bSmrg unsigned int ulVCOMax; 113eda3803bSmrg unsigned int ulVCOMin; 114eda3803bSmrg unsigned int ulPLLFreqRef; 115eda3803bSmrg 116eda3803bSmrg ulVCOMax = 550000; 117eda3803bSmrg ulVCOMin = 150000; 118eda3803bSmrg ulPLLFreqRef = 50000; 119eda3803bSmrg 120eda3803bSmrg ulFDelta = 0xFFFFFFFF; 121eda3803bSmrg /* Permited delta is 0.5% as VESA Specification */ 122eda3803bSmrg ulFPermitedDelta = lFo * 5 / 1000; 123eda3803bSmrg 124eda3803bSmrg /* Then we need to minimize the M while staying within 0.5% */ 125eda3803bSmrg for (ulTestP = 16; ulTestP > 0; ulTestP--) { 126fe5e51b7Smrg if ((lFo * ulTestP) > ulVCOMax) continue; 127fe5e51b7Smrg if ((lFo * ulTestP) < ulVCOMin) continue; 128fe5e51b7Smrg 129eda3803bSmrg for (ulTestN = 1; ulTestN <= 256; ulTestN++) { 130eda3803bSmrg for (ulTestM = 1; ulTestM <= 16; ulTestM++) { 131fe5e51b7Smrg ulComputedFo = (ulPLLFreqRef * ulTestN) / (ulTestM * ulTestP); 132fe5e51b7Smrg if (ulComputedFo > lFo) 133fe5e51b7Smrg ulFTmpDelta = ulComputedFo - lFo; 134fe5e51b7Smrg else 135fe5e51b7Smrg ulFTmpDelta = lFo - ulComputedFo; 136fe5e51b7Smrg 137fe5e51b7Smrg if (ulFTmpDelta < ulFDelta) { 138eda3803bSmrg ulFDelta = ulFTmpDelta; 139eda3803bSmrg *M = (CARD8)(ulTestM - 1); 140eda3803bSmrg *N = (CARD8)(ulTestN - 1); 141eda3803bSmrg *P = (CARD8)(ulTestP - 1); 142eda3803bSmrg } 143eda3803bSmrg } 144eda3803bSmrg } 145eda3803bSmrg } 146eda3803bSmrg#if DEBUG 147eda3803bSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 148eda3803bSmrg "lFo=%ld n=0x%x m=0x%x p=0x%x \n", 149eda3803bSmrg lFo, *N, *M, *P ); 150eda3803bSmrg#endif 151eda3803bSmrg} 152eda3803bSmrg 153eda3803bSmrgstatic void 154eda3803bSmrgMGAG200WBComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *M, int *N, int *P) 155eda3803bSmrg{ 156eda3803bSmrg unsigned int ulComputedFo; 157eda3803bSmrg unsigned int ulFDelta; 158eda3803bSmrg unsigned int ulFPermitedDelta; 159eda3803bSmrg unsigned int ulFTmpDelta; 160eda3803bSmrg unsigned int ulVCOMax, ulVCOMin; 161eda3803bSmrg unsigned int ulTestP; 162eda3803bSmrg unsigned int ulTestM; 163eda3803bSmrg unsigned int ulTestN; 164eda3803bSmrg unsigned int ulPLLFreqRef; 165eda3803bSmrg unsigned int ulTestPStart; 166eda3803bSmrg unsigned int ulTestNStart; 167eda3803bSmrg unsigned int ulTestNEnd; 168eda3803bSmrg unsigned int ulTestMStart; 169eda3803bSmrg unsigned int ulTestMEnd; 170eda3803bSmrg 171eda3803bSmrg ulVCOMax = 550000; 172eda3803bSmrg ulVCOMin = 150000; 173eda3803bSmrg ulPLLFreqRef = 48000; 174eda3803bSmrg ulTestPStart = 1; 175eda3803bSmrg ulTestNStart = 1; 176eda3803bSmrg ulTestNEnd = 150; 177eda3803bSmrg ulTestMStart = 1; 178eda3803bSmrg ulTestMEnd = 16; 179eda3803bSmrg 180eda3803bSmrg ulFDelta = 0xFFFFFFFF; 181eda3803bSmrg /* Permited delta is 0.5% as VESA Specification */ 182eda3803bSmrg ulFPermitedDelta = lFo * 5 / 1000; 183eda3803bSmrg 184eda3803bSmrg /* Then we need to minimize the M while staying within 0.5% */ 185eda3803bSmrg for (ulTestP = ulTestPStart; ulTestP < 9; ulTestP++) { 186eda3803bSmrg if ((lFo * ulTestP) > ulVCOMax) continue; 187eda3803bSmrg if ((lFo * ulTestP) < ulVCOMin) continue; 188eda3803bSmrg 189eda3803bSmrg for (ulTestM = ulTestMStart; ulTestM <= ulTestMEnd; ulTestM++) { 190eda3803bSmrg for (ulTestN = ulTestNStart; ulTestN <= ulTestNEnd; ulTestN++) { 191eda3803bSmrg ulComputedFo = (ulPLLFreqRef * ulTestN) / (ulTestM * ulTestP); 192eda3803bSmrg if (ulComputedFo > lFo) 193eda3803bSmrg ulFTmpDelta = ulComputedFo - lFo; 194eda3803bSmrg else 195eda3803bSmrg ulFTmpDelta = lFo - ulComputedFo; 196eda3803bSmrg 197eda3803bSmrg if (ulFTmpDelta < ulFDelta) { 198eda3803bSmrg ulFDelta = ulFTmpDelta; 199eda3803bSmrg *M = (CARD8)(ulTestM - 1) | (CARD8)(((ulTestN -1) >> 1) & 0x80); 200eda3803bSmrg *N = (CARD8)(ulTestN - 1); 201eda3803bSmrg *P = (CARD8)(ulTestP - 1); 202fe5e51b7Smrg } 203fe5e51b7Smrg } 204fe5e51b7Smrg } 205fe5e51b7Smrg } 206eda3803bSmrg#if DEBUG 207eda3803bSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 208eda3803bSmrg "lFo=%ld n=0x%x m=0x%x p=0x%x \n", 209eda3803bSmrg lFo, *N, *M, *P ); 210eda3803bSmrg#endif 211fe5e51b7Smrg} 212fe5e51b7Smrg 213a31a186aSmrgstatic void 214a31a186aSmrgMGAG200EHComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *M, int *N, int *P) 215a31a186aSmrg{ 216a31a186aSmrg unsigned int ulComputedFo; 217a31a186aSmrg unsigned int ulFDelta; 218a31a186aSmrg unsigned int ulFPermitedDelta; 219a31a186aSmrg unsigned int ulFTmpDelta; 220a31a186aSmrg unsigned int ulTestP; 221a31a186aSmrg unsigned int ulTestM; 222a31a186aSmrg unsigned int ulTestN; 223a31a186aSmrg unsigned int ulVCOMax; 224a31a186aSmrg unsigned int ulVCOMin; 225a31a186aSmrg unsigned int ulPLLFreqRef; 226a31a186aSmrg 227a31a186aSmrg ulVCOMax = 800000; 228a31a186aSmrg ulVCOMin = 400000; 229a31a186aSmrg ulPLLFreqRef = 33333; 230a31a186aSmrg 231a31a186aSmrg ulFDelta = 0xFFFFFFFF; 232a31a186aSmrg /* Permited delta is 0.5% as VESA Specification */ 233a31a186aSmrg ulFPermitedDelta = lFo * 5 / 1000; 234a31a186aSmrg 235a31a186aSmrg /* Then we need to minimize the M while staying within 0.5% */ 236a31a186aSmrg for (ulTestP = 16; ulTestP > 0; ulTestP>>= 1) { 237a31a186aSmrg if ((lFo * ulTestP) > ulVCOMax) continue; 238a31a186aSmrg if ((lFo * ulTestP) < ulVCOMin) continue; 239a31a186aSmrg 240a31a186aSmrg for (ulTestM = 1; ulTestM <= 32; ulTestM++) { 241a31a186aSmrg for (ulTestN = 17; ulTestN <= 256; ulTestN++) { 242a31a186aSmrg ulComputedFo = (ulPLLFreqRef * ulTestN) / (ulTestM * ulTestP); 243a31a186aSmrg if (ulComputedFo > lFo) 244a31a186aSmrg ulFTmpDelta = ulComputedFo - lFo; 245a31a186aSmrg else 246a31a186aSmrg ulFTmpDelta = lFo - ulComputedFo; 247a31a186aSmrg 248a31a186aSmrg if (ulFTmpDelta < ulFDelta) { 249a31a186aSmrg ulFDelta = ulFTmpDelta; 250a31a186aSmrg *M = (CARD8)(ulTestM - 1); 251a31a186aSmrg *N = (CARD8)(ulTestN - 1); 252a31a186aSmrg *P = (CARD8)(ulTestP - 1); 253a31a186aSmrg } 254a31a186aSmrg 255a31a186aSmrg if ((lFo * ulTestP) >= 600000) 256a31a186aSmrg *P |= 0x80; 257a31a186aSmrg } 258a31a186aSmrg } 259a31a186aSmrg } 260a31a186aSmrg} 261a31a186aSmrg 262eda3803bSmrgstatic void 263eda3803bSmrgMGAG200EVPIXPLLSET(ScrnInfoPtr pScrn, MGARegPtr mgaReg) 264eda3803bSmrg{ 265eda3803bSmrg MGAPtr pMga = MGAPTR(pScrn); 266eda3803bSmrg 267eda3803bSmrg unsigned char ucTempByte, ucPixCtrl; 268eda3803bSmrg 269eda3803bSmrg // Set pixclkdis to 1 270eda3803bSmrg ucPixCtrl = inMGAdac(MGA1064_PIX_CLK_CTL); 271eda3803bSmrg ucPixCtrl |= MGA1064_PIX_CLK_CTL_CLK_DIS; 272eda3803bSmrg outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl); 273eda3803bSmrg 274eda3803bSmrg // Select PLL Set C 275eda3803bSmrg ucTempByte = INREG8(MGAREG_MEM_MISC_READ); 276eda3803bSmrg ucTempByte |= 0x3<<2; //select MGA pixel clock 277eda3803bSmrg OUTREG8(MGAREG_MEM_MISC_WRITE, ucTempByte); 278eda3803bSmrg 279eda3803bSmrg // Set pixlock to 0 280eda3803bSmrg ucTempByte = inMGAdac(MGA1064_PIX_PLL_STAT); 281eda3803bSmrg outMGAdac(MGA1064_PIX_PLL_STAT, ucTempByte & ~0x40); 282eda3803bSmrg 283eda3803bSmrg // Set pix_stby to 1 284eda3803bSmrg ucPixCtrl |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; 285eda3803bSmrg outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl); 286eda3803bSmrg 287eda3803bSmrg // Program the Pixel PLL Register 288eda3803bSmrg outMGAdac(MGA1064_EV_PIX_PLLC_M, mgaReg->PllM); 289eda3803bSmrg outMGAdac(MGA1064_EV_PIX_PLLC_N, mgaReg->PllN); 290eda3803bSmrg outMGAdac(MGA1064_EV_PIX_PLLC_P, mgaReg->PllP); 291eda3803bSmrg 292eda3803bSmrg // Wait 50 us 293eda3803bSmrg usleep(50); 294eda3803bSmrg 295eda3803bSmrg // Set pix_stby to 0 296eda3803bSmrg ucPixCtrl &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; 297eda3803bSmrg outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl); 298eda3803bSmrg 299eda3803bSmrg // Wait 500 us 300eda3803bSmrg usleep(500); 301eda3803bSmrg 302eda3803bSmrg // Select the pixel PLL by setting pixclksel to 1 303eda3803bSmrg ucTempByte = inMGAdac(MGA1064_PIX_CLK_CTL); 304eda3803bSmrg ucTempByte &= ~MGA1064_PIX_CLK_CTL_SEL_MSK; 305eda3803bSmrg ucTempByte |= MGA1064_PIX_CLK_CTL_SEL_PLL; 306eda3803bSmrg outMGAdac(MGA1064_PIX_CLK_CTL, ucTempByte); 307eda3803bSmrg 308eda3803bSmrg // Set pixlock to 1 309eda3803bSmrg ucTempByte = inMGAdac(MGA1064_PIX_PLL_STAT); 310eda3803bSmrg outMGAdac(MGA1064_PIX_CLK_CTL, ucTempByte | 0x40); 311eda3803bSmrg 312eda3803bSmrg // Reset dotclock rate bit. 313eda3803bSmrg ucTempByte = INREG8(MGAREG_MEM_MISC_READ); 314eda3803bSmrg ucTempByte |= 0x3<<2; //select MGA pixel clock 315eda3803bSmrg OUTREG8(MGAREG_MEM_MISC_WRITE, ucTempByte); 316eda3803bSmrg 317eda3803bSmrg OUTREG8(MGAREG_SEQ_INDEX, 1); 318eda3803bSmrg ucTempByte = INREG8(MGAREG_SEQ_DATA); 319eda3803bSmrg OUTREG8(MGAREG_SEQ_DATA, ucTempByte & ~0x8); 320eda3803bSmrg 321eda3803bSmrg // Set pixclkdis to 0 322eda3803bSmrg ucTempByte = inMGAdac(MGA1064_PIX_CLK_CTL); 323eda3803bSmrg ucTempByte &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; 324eda3803bSmrg outMGAdac(MGA1064_PIX_CLK_CTL, ucTempByte); 325eda3803bSmrg} 326eda3803bSmrg 327eda3803bSmrgstatic void 328eda3803bSmrgMGAG200WBPIXPLLSET(ScrnInfoPtr pScrn, MGARegPtr mgaReg) 329eda3803bSmrg{ 330eda3803bSmrg MGAPtr pMga = MGAPTR(pScrn); 331eda3803bSmrg 332eda3803bSmrg unsigned long ulLoopCount, ulLockCheckIterations = 0, ulTempCount, ulVCount; 333eda3803bSmrg unsigned char ucTempByte, ucPixCtrl, ucPLLLocked = FALSE; 334eda3803bSmrg 335eda3803bSmrg while(ulLockCheckIterations <= 32 && ucPLLLocked == FALSE) 336eda3803bSmrg { 337eda3803bSmrg if(ulLockCheckIterations > 0) 338eda3803bSmrg { 339eda3803bSmrg OUTREG8(MGAREG_CRTCEXT_INDEX, 0x1E); 340eda3803bSmrg ucTempByte = INREG8(MGAREG_CRTCEXT_DATA); 341eda3803bSmrg if(ucTempByte < 0xFF) 342eda3803bSmrg { 343eda3803bSmrg OUTREG8(MGAREG_CRTCEXT_DATA, ucTempByte+1); 344eda3803bSmrg } 345eda3803bSmrg } 346eda3803bSmrg 347eda3803bSmrg // Set pixclkdis to 1 348eda3803bSmrg ucPixCtrl = inMGAdac(MGA1064_PIX_CLK_CTL); 349eda3803bSmrg ucPixCtrl |= MGA1064_PIX_CLK_CTL_CLK_DIS; 350eda3803bSmrg outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl); 351eda3803bSmrg 352eda3803bSmrg ucTempByte = inMGAdac(MGA1064_REMHEADCTL); 353eda3803bSmrg ucTempByte |= MGA1064_REMHEADCTL_CLKDIS; 354eda3803bSmrg outMGAdac(MGA1064_REMHEADCTL, ucTempByte); 355eda3803bSmrg 356eda3803bSmrg // Select PLL Set C 357eda3803bSmrg ucTempByte = INREG8(MGAREG_MEM_MISC_READ); 358eda3803bSmrg ucTempByte |= 0x3<<2; //select MGA pixel clock 359eda3803bSmrg OUTREG8(MGAREG_MEM_MISC_WRITE, ucTempByte); 360eda3803bSmrg 361eda3803bSmrg ucPixCtrl |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN | 0x80; 362eda3803bSmrg outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl); 363eda3803bSmrg 364eda3803bSmrg // Wait 500 us 365eda3803bSmrg usleep(500); 366eda3803bSmrg 367eda3803bSmrg // Reset the PLL 368eda3803bSmrg // When we are varying the output frequency by more than 369eda3803bSmrg // 10%, we must reset the PLL. However to be prudent, we 370eda3803bSmrg // will reset it each time that we are changing it. 371eda3803bSmrg ucTempByte = inMGAdac(MGA1064_VREF_CTL); 372eda3803bSmrg ucTempByte &= ~0x04; 373eda3803bSmrg outMGAdac(MGA1064_VREF_CTL, ucTempByte ); 374eda3803bSmrg 375eda3803bSmrg // Wait 50 us 376eda3803bSmrg usleep(50); 377eda3803bSmrg 378eda3803bSmrg // Program the Pixel PLL Register 379eda3803bSmrg outMGAdac(MGA1064_WB_PIX_PLLC_N, mgaReg->PllN); 380a31a186aSmrg outMGAdac(MGA1064_WB_PIX_PLLC_M, mgaReg->PllM); 381eda3803bSmrg outMGAdac(MGA1064_WB_PIX_PLLC_P, mgaReg->PllP); 382eda3803bSmrg 383eda3803bSmrg // Wait 50 us 384eda3803bSmrg usleep(50); 385eda3803bSmrg 386eda3803bSmrg // Turning the PLL on 387eda3803bSmrg ucTempByte = inMGAdac(MGA1064_VREF_CTL); 388eda3803bSmrg ucTempByte |= 0x04; 389eda3803bSmrg outMGAdac(MGA1064_VREF_CTL, ucTempByte ); 390eda3803bSmrg 391eda3803bSmrg // Wait 500 us 392eda3803bSmrg usleep(500); 393eda3803bSmrg 394eda3803bSmrg // Select the pixel PLL by setting pixclksel to 1 395eda3803bSmrg ucTempByte = inMGAdac(MGA1064_PIX_CLK_CTL); 396eda3803bSmrg ucTempByte &= ~MGA1064_PIX_CLK_CTL_SEL_MSK; 397eda3803bSmrg ucTempByte |= MGA1064_PIX_CLK_CTL_SEL_PLL; 398eda3803bSmrg outMGAdac(MGA1064_PIX_CLK_CTL, ucTempByte); 399eda3803bSmrg 400eda3803bSmrg ucTempByte = inMGAdac(MGA1064_REMHEADCTL); 401eda3803bSmrg ucTempByte &= ~MGA1064_REMHEADCTL_CLKSL_MSK; 402eda3803bSmrg ucTempByte |= MGA1064_REMHEADCTL_CLKSL_PLL; 403eda3803bSmrg outMGAdac(MGA1064_REMHEADCTL, ucTempByte); 404eda3803bSmrg 405eda3803bSmrg // Reset dotclock rate bit. 406eda3803bSmrg OUTREG8(MGAREG_SEQ_INDEX, 1); 407eda3803bSmrg ucTempByte = INREG8(MGAREG_SEQ_DATA); 408eda3803bSmrg OUTREG8(MGAREG_SEQ_DATA, ucTempByte & ~0x8); 409eda3803bSmrg 410eda3803bSmrg // Set pixclkdis to 0 411eda3803bSmrg ucTempByte = inMGAdac(MGA1064_PIX_CLK_CTL); 412eda3803bSmrg ucTempByte &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; 413eda3803bSmrg outMGAdac(MGA1064_PIX_CLK_CTL, ucTempByte); 414eda3803bSmrg 415eda3803bSmrg // Poll VCount. If it increments twice inside 150us, 416eda3803bSmrg // we assume that the PLL has locked. 417eda3803bSmrg ulLoopCount = 0; 418eda3803bSmrg ulVCount = INREG(MGAREG_VCOUNT); 419eda3803bSmrg 420eda3803bSmrg while(ulLoopCount < 30 && ucPLLLocked == FALSE) 421eda3803bSmrg { 422eda3803bSmrg ulTempCount = INREG(MGAREG_VCOUNT); 423eda3803bSmrg 424eda3803bSmrg if(ulTempCount < ulVCount) 425eda3803bSmrg { 426eda3803bSmrg ulVCount = 0; 427eda3803bSmrg } 428eda3803bSmrg if ((ucTempByte - ulVCount) > 2) 429eda3803bSmrg { 430eda3803bSmrg ucPLLLocked = TRUE; 431eda3803bSmrg } 432eda3803bSmrg else 433eda3803bSmrg { 434eda3803bSmrg usleep(5); 435eda3803bSmrg } 436eda3803bSmrg ulLoopCount++; 437eda3803bSmrg } 438eda3803bSmrg ulLockCheckIterations++; 439eda3803bSmrg } 440eda3803bSmrg 441eda3803bSmrg // Set remclkdis to 0 442eda3803bSmrg ucTempByte = inMGAdac(MGA1064_REMHEADCTL); 443eda3803bSmrg ucTempByte &= ~MGA1064_REMHEADCTL_CLKDIS; 444eda3803bSmrg outMGAdac(MGA1064_REMHEADCTL, ucTempByte); 445eda3803bSmrg} 446eda3803bSmrg 447eda3803bSmrgstatic void 448eda3803bSmrgMGAG200WBPrepareForModeSwitch(ScrnInfoPtr pScrn) 449eda3803bSmrg{ 450eda3803bSmrg MGAPtr pMga = MGAPTR(pScrn); 451eda3803bSmrg 452eda3803bSmrg unsigned char ucTmpData = 0; 453eda3803bSmrg int ulIterationMax = 0; 454eda3803bSmrg // 1- The first step is to warn the BMC of an upcoming mode change. 455eda3803bSmrg // We are putting the misc<0> to output. 456eda3803bSmrg ucTmpData = inMGAdac(MGA1064_GEN_IO_CTL); 457eda3803bSmrg ucTmpData |= 0x10; 458eda3803bSmrg outMGAdac(MGA1064_GEN_IO_CTL, ucTmpData); 459eda3803bSmrg 460eda3803bSmrg // We are putting a 1 on the misc<0> line. 461eda3803bSmrg ucTmpData = inMGAdac(MGA1064_GEN_IO_DATA); 462eda3803bSmrg ucTmpData |= 0x10; 463eda3803bSmrg outMGAdac(MGA1064_GEN_IO_DATA, ucTmpData); 464eda3803bSmrg 465eda3803bSmrg // 2- The second step is to mask any further scan request 466eda3803bSmrg // This will be done by asserting the remfreqmsk bit (XSPAREREG<7>) 467eda3803bSmrg ucTmpData = inMGAdac(MGA1064_SPAREREG); 468eda3803bSmrg ucTmpData |= 0x80; 469eda3803bSmrg outMGAdac(MGA1064_SPAREREG, ucTmpData); 470eda3803bSmrg 471eda3803bSmrg // 3a- The third step is to verify if there is an active scan 472eda3803bSmrg // We are searching for a 0 on remhsyncsts (XSPAREREG<0>) 473eda3803bSmrg ulIterationMax = 300; 474eda3803bSmrg while (!(ucTmpData & 0x01) && ulIterationMax) 475eda3803bSmrg { 476eda3803bSmrg ucTmpData = inMGAdac(MGA1064_SPAREREG); 477eda3803bSmrg usleep(1000); 478eda3803bSmrg ulIterationMax--; 479eda3803bSmrg } 480eda3803bSmrg 481eda3803bSmrg // 3b- This step occurs only if the remote is actually scanning 482eda3803bSmrg // We are waiting for the end of the frame which is a 1 on 483eda3803bSmrg // remvsyncsts (XSPAREREG<1>) 484eda3803bSmrg if (ulIterationMax) 485eda3803bSmrg { 486eda3803bSmrg ulIterationMax = 300; 487eda3803bSmrg while ((ucTmpData & 0x02) && ulIterationMax) 488eda3803bSmrg { 489eda3803bSmrg ucTmpData = inMGAdac(MGA1064_SPAREREG); 490eda3803bSmrg usleep(1000); 491eda3803bSmrg ulIterationMax--; 492eda3803bSmrg } 493eda3803bSmrg } 494eda3803bSmrg} 495eda3803bSmrg 496eda3803bSmrgstatic void 497eda3803bSmrgMGAG200WBRestoreFromModeSwitch(ScrnInfoPtr pScrn) 498eda3803bSmrg{ 499eda3803bSmrg MGAPtr pMga = MGAPTR(pScrn); 500eda3803bSmrg 501eda3803bSmrg unsigned char ucTmpData = 0; 502eda3803bSmrg 503eda3803bSmrg // 1- The first step is to ensure that the vrsten and hrsten are set 504eda3803bSmrg OUTREG8(MGAREG_CRTCEXT_INDEX, 0x01); 505eda3803bSmrg ucTmpData = INREG8(MGAREG_CRTCEXT_DATA); 506eda3803bSmrg OUTREG8(MGAREG_CRTCEXT_DATA, ucTmpData | 0x88); 507eda3803bSmrg 508eda3803bSmrg // 2- The second step is is to assert the rstlvl2 509eda3803bSmrg ucTmpData = inMGAdac(MGA1064_REMHEADCTL2); 510eda3803bSmrg ucTmpData |= 0x08; 511eda3803bSmrg outMGAdac(MGA1064_REMHEADCTL2, ucTmpData); 512eda3803bSmrg 513eda3803bSmrg // - Wait for 10 us 514eda3803bSmrg usleep(10); 515eda3803bSmrg 516eda3803bSmrg // 3- The next step is is to deassert the rstlvl2 517eda3803bSmrg ucTmpData &= ~0x08; 518eda3803bSmrg outMGAdac(MGA1064_REMHEADCTL2, ucTmpData); 519eda3803bSmrg 520eda3803bSmrg // - Wait for 10 us 521eda3803bSmrg usleep(10); 522eda3803bSmrg 523eda3803bSmrg // 4- The fourth step is to remove the mask of scan request 524eda3803bSmrg // This will be done by deasserting the remfreqmsk bit (XSPAREREG<7>) 525eda3803bSmrg ucTmpData = inMGAdac(MGA1064_SPAREREG); 526eda3803bSmrg ucTmpData &= ~0x80; 527eda3803bSmrg outMGAdac(MGA1064_SPAREREG, ucTmpData); 528eda3803bSmrg 529eda3803bSmrg // 5- Finally, we are putting back a 0 on the misc<0> line. 530eda3803bSmrg ucTmpData = inMGAdac(MGA1064_GEN_IO_DATA); 531eda3803bSmrg ucTmpData &= ~0x10; 532eda3803bSmrg outMGAdac(MGA1064_GEN_IO_DATA, ucTmpData); 533eda3803bSmrg} 534fe5e51b7Smrg 535a31a186aSmrgstatic void 536a31a186aSmrgMGAG200EHPIXPLLSET(ScrnInfoPtr pScrn, MGARegPtr mgaReg) 537a31a186aSmrg{ 538a31a186aSmrg MGAPtr pMga = MGAPTR(pScrn); 539a31a186aSmrg 540a31a186aSmrg unsigned long ulFallBackCounter, ulLoopCount, ulLockCheckIterations = 0, ulTempCount, ulVCount; 541a31a186aSmrg unsigned char ucTempByte, ucPixCtrl, ucPLLLocked = FALSE; 542a31a186aSmrg unsigned char ucM; 543a31a186aSmrg unsigned char ucN; 544a31a186aSmrg unsigned char ucP; 545a31a186aSmrg unsigned char ucS; 546a31a186aSmrg 547a31a186aSmrg while(ulLockCheckIterations <= 32 && ucPLLLocked == FALSE) 548a31a186aSmrg { 549a31a186aSmrg // Set pixclkdis to 1 550a31a186aSmrg ucPixCtrl = inMGAdac(MGA1064_PIX_CLK_CTL); 551a31a186aSmrg ucPixCtrl |= MGA1064_PIX_CLK_CTL_CLK_DIS; 552a31a186aSmrg outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl); 553a31a186aSmrg 554a31a186aSmrg // Select PLL Set C 555a31a186aSmrg ucTempByte = INREG8(MGAREG_MEM_MISC_READ); 556a31a186aSmrg ucTempByte |= 0x3<<2; //select MGA pixel clock 557a31a186aSmrg OUTREG8(MGAREG_MEM_MISC_WRITE, ucTempByte); 558a31a186aSmrg 559a31a186aSmrg ucPixCtrl |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; 560a31a186aSmrg ucPixCtrl &= ~0x80; 561a31a186aSmrg outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl); 562a31a186aSmrg 563a31a186aSmrg // Wait 500 us 564a31a186aSmrg usleep(500); 565a31a186aSmrg 566a31a186aSmrg // Program the Pixel PLL Register 567a31a186aSmrg outMGAdac(MGA1064_EH_PIX_PLLC_N, mgaReg->PllN); 568a31a186aSmrg outMGAdac(MGA1064_EH_PIX_PLLC_M, mgaReg->PllM); 569a31a186aSmrg outMGAdac(MGA1064_EH_PIX_PLLC_P, mgaReg->PllP); 570a31a186aSmrg 571a31a186aSmrg // Wait 500 us 572a31a186aSmrg usleep(500); 573a31a186aSmrg 574a31a186aSmrg // Select the pixel PLL by setting pixclksel to 1 575a31a186aSmrg ucTempByte = inMGAdac(MGA1064_PIX_CLK_CTL); 576a31a186aSmrg ucTempByte &= ~MGA1064_PIX_CLK_CTL_SEL_MSK; 577a31a186aSmrg ucTempByte |= MGA1064_PIX_CLK_CTL_SEL_PLL; 578a31a186aSmrg outMGAdac(MGA1064_PIX_CLK_CTL, ucTempByte); 579a31a186aSmrg 580a31a186aSmrg // Reset dotclock rate bit. 581a31a186aSmrg OUTREG8(MGAREG_SEQ_INDEX, 1); 582a31a186aSmrg ucTempByte = INREG8(MGAREG_SEQ_DATA); 583a31a186aSmrg OUTREG8(MGAREG_SEQ_DATA, ucTempByte & ~0x8); 584a31a186aSmrg 585a31a186aSmrg // Set pixclkdis to 0 and pixplldn to 0 586a31a186aSmrg ucTempByte = inMGAdac(MGA1064_PIX_CLK_CTL); 587a31a186aSmrg ucTempByte &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; 588a31a186aSmrg ucTempByte &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; 589a31a186aSmrg outMGAdac(MGA1064_PIX_CLK_CTL, ucTempByte); 590a31a186aSmrg 591a31a186aSmrg // Poll VCount. If it increments twice inside 150us, 592a31a186aSmrg // we assume that the PLL has locked. 593a31a186aSmrg ulLoopCount = 0; 594a31a186aSmrg ulVCount = INREG(MGAREG_VCOUNT); 595a31a186aSmrg 596a31a186aSmrg while(ulLoopCount < 30 && ucPLLLocked == FALSE) 597a31a186aSmrg { 598a31a186aSmrg ulTempCount = INREG(MGAREG_VCOUNT); 599a31a186aSmrg 600a31a186aSmrg if(ulTempCount < ulVCount) 601a31a186aSmrg { 602a31a186aSmrg ulVCount = 0; 603a31a186aSmrg } 604a31a186aSmrg if ((ucTempByte - ulVCount) > 2) 605a31a186aSmrg { 606a31a186aSmrg ucPLLLocked = TRUE; 607a31a186aSmrg } 608a31a186aSmrg else 609a31a186aSmrg { 610a31a186aSmrg usleep(5); 611a31a186aSmrg } 612a31a186aSmrg ulLoopCount++; 613a31a186aSmrg } 614a31a186aSmrg ulLockCheckIterations++; 615a31a186aSmrg } 616a31a186aSmrg} 617a31a186aSmrg 618fe5e51b7Smrg/** 619fe5e51b7Smrg * Calculate the PLL settings (m, n, p, s). 620fe5e51b7Smrg * 621fe5e51b7Smrg * For more information, refer to the Matrox "MGA1064SG Developer 622fe5e51b7Smrg * Specification" (document 10524-MS-0100). chapter 5.7.8. "PLLs Clocks 623fe5e51b7Smrg * Generators" 624fe5e51b7Smrg * 625fe5e51b7Smrg * \param f_out Desired clock frequency, measured in kHz. 626fe5e51b7Smrg * \param best_m Value of PLL 'm' register. 627fe5e51b7Smrg * \param best_n Value of PLL 'n' register. 628fe5e51b7Smrg * \param p Value of PLL 'p' register. 629fe5e51b7Smrg * \param s Value of PLL 's' filter register (pix pll clock only). 630fe5e51b7Smrg */ 631fe5e51b7Smrg 632fe5e51b7Smrgstatic void 633fe5e51b7SmrgMGAGCalcClock ( ScrnInfoPtr pScrn, long f_out, 634fe5e51b7Smrg int *best_m, int *best_n, int *p, int *s ) 635fe5e51b7Smrg{ 636fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 637fe5e51b7Smrg int m, n; 638fe5e51b7Smrg double f_vco; 639fe5e51b7Smrg double m_err, calc_f; 640fe5e51b7Smrg const double ref_freq = (double) pMga->bios.pll_ref_freq; 641fe5e51b7Smrg const int feed_div_max = 127; 642fe5e51b7Smrg const int in_div_min = 1; 643fe5e51b7Smrg const int post_div_max = 7; 644fe5e51b7Smrg int feed_div_min; 645fe5e51b7Smrg int in_div_max; 646fe5e51b7Smrg 647fe5e51b7Smrg 648fe5e51b7Smrg switch( pMga->Chipset ) 649fe5e51b7Smrg { 650fe5e51b7Smrg case PCI_CHIP_MGA1064: 651fe5e51b7Smrg feed_div_min = 100; 652fe5e51b7Smrg in_div_max = 31; 653fe5e51b7Smrg break; 654fe5e51b7Smrg case PCI_CHIP_MGAG400: 655fe5e51b7Smrg case PCI_CHIP_MGAG550: 656fe5e51b7Smrg feed_div_min = 7; 657fe5e51b7Smrg in_div_max = 31; 658fe5e51b7Smrg break; 659fe5e51b7Smrg case PCI_CHIP_MGAG200_SE_A_PCI: 660fe5e51b7Smrg case PCI_CHIP_MGAG200_SE_B_PCI: 661fe5e51b7Smrg case PCI_CHIP_MGAG100: 662fe5e51b7Smrg case PCI_CHIP_MGAG100_PCI: 663fe5e51b7Smrg case PCI_CHIP_MGAG200: 664fe5e51b7Smrg case PCI_CHIP_MGAG200_PCI: 665fe5e51b7Smrg default: 666fe5e51b7Smrg feed_div_min = 7; 667fe5e51b7Smrg in_div_max = 6; 668fe5e51b7Smrg break; 669fe5e51b7Smrg } 670fe5e51b7Smrg 671fe5e51b7Smrg /* Make sure that f_min <= f_out */ 672fe5e51b7Smrg if ( f_out < ( pMga->bios.pixel.min_freq / 8)) 673fe5e51b7Smrg f_out = pMga->bios.pixel.min_freq / 8; 674fe5e51b7Smrg 675fe5e51b7Smrg /* 676fe5e51b7Smrg * f_pll = f_vco / (p+1) 677fe5e51b7Smrg * Choose p so that 678fe5e51b7Smrg * pMga->bios.pixel.min_freq <= f_vco <= pMga->bios.pixel.max_freq 679fe5e51b7Smrg * we don't have to bother checking for this maximum limit. 680fe5e51b7Smrg */ 681fe5e51b7Smrg f_vco = ( double ) f_out; 682fe5e51b7Smrg for ( *p = 0; *p <= post_div_max && f_vco < pMga->bios.pixel.min_freq; 683fe5e51b7Smrg *p = *p * 2 + 1, f_vco *= 2.0); 684fe5e51b7Smrg 685fe5e51b7Smrg /* Initial amount of error for frequency maximum */ 686fe5e51b7Smrg m_err = f_out; 687fe5e51b7Smrg 688fe5e51b7Smrg /* Search for the different values of ( m ) */ 689fe5e51b7Smrg for ( m = in_div_min ; m <= in_div_max ; m++ ) 690fe5e51b7Smrg { 691fe5e51b7Smrg /* see values of ( n ) which we can't use */ 692fe5e51b7Smrg for ( n = feed_div_min; n <= feed_div_max; n++ ) 693fe5e51b7Smrg { 694fe5e51b7Smrg calc_f = ref_freq * (n + 1) / (m + 1) ; 695fe5e51b7Smrg 696fe5e51b7Smrg /* 697fe5e51b7Smrg * Pick the closest frequency. 698fe5e51b7Smrg */ 699fe5e51b7Smrg if ( abs(calc_f - f_vco) < m_err ) { 700fe5e51b7Smrg m_err = abs(calc_f - f_vco); 701fe5e51b7Smrg *best_m = m; 702fe5e51b7Smrg *best_n = n; 703fe5e51b7Smrg } 704fe5e51b7Smrg } 705fe5e51b7Smrg } 706fe5e51b7Smrg 707fe5e51b7Smrg /* Now all the calculations can be completed */ 708fe5e51b7Smrg f_vco = ref_freq * (*best_n + 1) / (*best_m + 1); 709fe5e51b7Smrg 710fe5e51b7Smrg /* Adjustments for filtering pll feed back */ 711fe5e51b7Smrg if ( (50000.0 <= f_vco) 712fe5e51b7Smrg && (f_vco < 100000.0) ) 713fe5e51b7Smrg *s = 0; 714fe5e51b7Smrg if ( (100000.0 <= f_vco) 715fe5e51b7Smrg && (f_vco < 140000.0) ) 716fe5e51b7Smrg *s = 1; 717fe5e51b7Smrg if ( (140000.0 <= f_vco) 718fe5e51b7Smrg && (f_vco < 180000.0) ) 719fe5e51b7Smrg *s = 2; 720fe5e51b7Smrg if ( (180000.0 <= f_vco) ) 721fe5e51b7Smrg *s = 3; 722fe5e51b7Smrg 723fe5e51b7Smrg#ifdef DEBUG 724fe5e51b7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 725fe5e51b7Smrg "f_out_requ =%ld f_pll_real=%.1f f_vco=%.1f n=0x%x m=0x%x p=0x%x s=0x%x\n", 726fe5e51b7Smrg f_out, (f_vco / (*p + 1)), f_vco, *best_n, *best_m, *p, *s ); 727fe5e51b7Smrg#endif 728fe5e51b7Smrg} 729fe5e51b7Smrg 730fe5e51b7Smrg/* 731fe5e51b7Smrg * MGAGSetPCLK - Set the pixel (PCLK) clock. 732fe5e51b7Smrg */ 733fe5e51b7Smrgstatic void 734fe5e51b7SmrgMGAGSetPCLK( ScrnInfoPtr pScrn, long f_out ) 735fe5e51b7Smrg{ 736fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 737fe5e51b7Smrg MGARegPtr pReg = &pMga->ModeReg; 738fe5e51b7Smrg 739fe5e51b7Smrg /* Pixel clock values */ 740fe5e51b7Smrg int m, n, p, s; 741eda3803bSmrg m = n = p = s = 0; 742fe5e51b7Smrg 743fe5e51b7Smrg if(MGAISGx50(pMga)) { 744fe5e51b7Smrg pReg->Clock = f_out; 745fe5e51b7Smrg return; 746fe5e51b7Smrg } 747fe5e51b7Smrg 748fe5e51b7Smrg if (pMga->is_G200SE) { 749fe5e51b7Smrg MGAG200SEComputePLLParam(pScrn, f_out, &m, &n, &p); 750fe5e51b7Smrg 751fe5e51b7Smrg pReg->DacRegs[ MGA1064_PIX_PLLC_M ] = m; 752fe5e51b7Smrg pReg->DacRegs[ MGA1064_PIX_PLLC_N ] = n; 753fe5e51b7Smrg pReg->DacRegs[ MGA1064_PIX_PLLC_P ] = p; 754eda3803bSmrg } else if (pMga->is_G200EV) { 755eda3803bSmrg MGAG200EVComputePLLParam(pScrn, f_out, &m, &n, &p); 756eda3803bSmrg 757eda3803bSmrg pReg->PllM = m; 758eda3803bSmrg pReg->PllN = n; 759eda3803bSmrg pReg->PllP = p; 760eda3803bSmrg } else if (pMga->is_G200WB) { 761eda3803bSmrg MGAG200WBComputePLLParam(pScrn, f_out, &m, &n, &p); 762eda3803bSmrg 763a31a186aSmrg pReg->PllM = m; 764a31a186aSmrg pReg->PllN = n; 765a31a186aSmrg pReg->PllP = p; 766a31a186aSmrg } else if (pMga->is_G200EH) { 767a31a186aSmrg MGAG200EHComputePLLParam(pScrn, f_out, &m, &n, &p); 768a31a186aSmrg 769eda3803bSmrg pReg->PllM = m; 770eda3803bSmrg pReg->PllN = n; 771eda3803bSmrg pReg->PllP = p; 772eda3803bSmrg } else { 773fe5e51b7Smrg /* Do the calculations for m, n, p and s */ 774fe5e51b7Smrg MGAGCalcClock( pScrn, f_out, &m, &n, &p, &s ); 775fe5e51b7Smrg 776fe5e51b7Smrg /* Values for the pixel clock PLL registers */ 777fe5e51b7Smrg pReg->DacRegs[ MGA1064_PIX_PLLC_M ] = m & 0x1F; 778fe5e51b7Smrg pReg->DacRegs[ MGA1064_PIX_PLLC_N ] = n & 0x7F; 779fe5e51b7Smrg pReg->DacRegs[ MGA1064_PIX_PLLC_P ] = (p & 0x07) | 780fe5e51b7Smrg ((s & 0x03) << 3); 781fe5e51b7Smrg } 782fe5e51b7Smrg} 783fe5e51b7Smrg 784fe5e51b7Smrg/* 785fe5e51b7Smrg * MGAGInit 786fe5e51b7Smrg */ 787fe5e51b7Smrgstatic Bool 788fe5e51b7SmrgMGAGInit(ScrnInfoPtr pScrn, DisplayModePtr mode) 789fe5e51b7Smrg{ 790fe5e51b7Smrg /* 791fe5e51b7Smrg * initial values of the DAC registers 792fe5e51b7Smrg */ 793fe5e51b7Smrg const static unsigned char initDAC[] = { 794fe5e51b7Smrg /* 0x00: */ 0, 0, 0, 0, 0, 0, 0x00, 0, 795fe5e51b7Smrg /* 0x08: */ 0, 0, 0, 0, 0, 0, 0, 0, 796fe5e51b7Smrg /* 0x10: */ 0, 0, 0, 0, 0, 0, 0, 0, 797fe5e51b7Smrg /* 0x18: */ 0x00, 0, 0xC9, 0xFF, 0xBF, 0x20, 0x1F, 0x20, 798fe5e51b7Smrg /* 0x20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 799fe5e51b7Smrg /* 0x28: */ 0x00, 0x00, 0x00, 0x00, 0, 0, 0, 0x40, 800fe5e51b7Smrg /* 0x30: */ 0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83, 801fe5e51b7Smrg /* 0x38: */ 0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A, 802fe5e51b7Smrg /* 0x40: */ 0, 0, 0, 0, 0, 0, 0, 0, 803fe5e51b7Smrg /* 0x48: */ 0, 0, 0, 0, 0, 0, 0, 0 804fe5e51b7Smrg }; 805fe5e51b7Smrg 806fe5e51b7Smrg int i; 807fe5e51b7Smrg int hd, hs, he, ht, vd, vs, ve, vt, wd; 808fe5e51b7Smrg int BppShift; 809fe5e51b7Smrg MGAPtr pMga; 810fe5e51b7Smrg MGARegPtr pReg; 811fe5e51b7Smrg vgaRegPtr pVga; 812fe5e51b7Smrg MGAFBLayout *pLayout; 813fe5e51b7Smrg xMODEINFO ModeInfo; 814fe5e51b7Smrg 815fe5e51b7Smrg ModeInfo.ulDispWidth = mode->HDisplay; 816fe5e51b7Smrg ModeInfo.ulDispHeight = mode->VDisplay; 817fe5e51b7Smrg ModeInfo.ulFBPitch = mode->HDisplay; 818fe5e51b7Smrg ModeInfo.ulBpp = pScrn->bitsPerPixel; 819fe5e51b7Smrg ModeInfo.flSignalMode = 0; 820fe5e51b7Smrg ModeInfo.ulPixClock = mode->Clock; 821fe5e51b7Smrg ModeInfo.ulHFPorch = mode->HSyncStart - mode->HDisplay; 822fe5e51b7Smrg ModeInfo.ulHSync = mode->HSyncEnd - mode->HSyncStart; 823fe5e51b7Smrg ModeInfo.ulHBPorch = mode->HTotal - mode->HSyncEnd; 824fe5e51b7Smrg ModeInfo.ulVFPorch = mode->VSyncStart - mode->VDisplay; 825fe5e51b7Smrg ModeInfo.ulVSync = mode->VSyncEnd - mode->VSyncStart; 826fe5e51b7Smrg ModeInfo.ulVBPorch = mode->VTotal - mode->VSyncEnd; 827fe5e51b7Smrg 828fe5e51b7Smrg pMga = MGAPTR(pScrn); 829fe5e51b7Smrg pReg = &pMga->ModeReg; 830fe5e51b7Smrg pVga = &VGAHWPTR(pScrn)->ModeReg; 831fe5e51b7Smrg pLayout = &pMga->CurrentLayout; 832fe5e51b7Smrg 833fe5e51b7Smrg BppShift = pMga->BppShifts[(pLayout->bitsPerPixel >> 3) - 1]; 834fe5e51b7Smrg 835fe5e51b7Smrg MGA_NOT_HAL( 836fe5e51b7Smrg /* Allocate the DacRegs space if not done already */ 837fe5e51b7Smrg if (pReg->DacRegs == NULL) { 838fe5e51b7Smrg pReg->DacRegs = xnfcalloc(DACREGSIZE, 1); 839fe5e51b7Smrg } 840fe5e51b7Smrg for (i = 0; i < DACREGSIZE; i++) { 841fe5e51b7Smrg pReg->DacRegs[i] = initDAC[i]; 842fe5e51b7Smrg } 843fe5e51b7Smrg ); /* MGA_NOT_HAL */ 844fe5e51b7Smrg 845fe5e51b7Smrg switch(pMga->Chipset) 846fe5e51b7Smrg { 847fe5e51b7Smrg case PCI_CHIP_MGA1064: 848fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x04; 849fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x44; 850fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18; 851fe5e51b7Smrg pReg->Option = 0x5F094F21; 852fe5e51b7Smrg pReg->Option2 = 0x00000000; 853fe5e51b7Smrg break; 854fe5e51b7Smrg case PCI_CHIP_MGAG100: 855fe5e51b7Smrg case PCI_CHIP_MGAG100_PCI: 856fe5e51b7Smrg pReg->DacRegs[MGA1064_VREF_CTL] = 0x03; 857fe5e51b7Smrg 858fe5e51b7Smrg if(pMga->HasSDRAM) { 859fe5e51b7Smrg if(pMga->OverclockMem) { 860fe5e51b7Smrg /* 220 Mhz */ 861fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x06; 862fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x38; 863fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18; 864fe5e51b7Smrg } else { 865fe5e51b7Smrg /* 203 Mhz */ 866fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x01; 867fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x0E; 868fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18; 869fe5e51b7Smrg } 870fe5e51b7Smrg pReg->Option = 0x404991a9; 871fe5e51b7Smrg } else { 872fe5e51b7Smrg if(pMga->OverclockMem) { 873fe5e51b7Smrg /* 143 Mhz */ 874fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x06; 875fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x24; 876fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x10; 877fe5e51b7Smrg } else { 878fe5e51b7Smrg /* 124 Mhz */ 879fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x04; 880fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x16; 881fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x08; 882fe5e51b7Smrg } 883fe5e51b7Smrg pReg->Option = 0x4049d121; 884fe5e51b7Smrg } 885fe5e51b7Smrg pReg->Option2 = 0x0000007; 886fe5e51b7Smrg break; 887fe5e51b7Smrg case PCI_CHIP_MGAG400: 888fe5e51b7Smrg case PCI_CHIP_MGAG550: 889fe5e51b7Smrg#ifdef USEMGAHAL 890fe5e51b7Smrg MGA_HAL(break;); 891fe5e51b7Smrg#endif 892fe5e51b7Smrg if (MGAISGx50(pMga)) 893fe5e51b7Smrg break; 894fe5e51b7Smrg 895fe5e51b7Smrg if(pMga->Dac.maxPixelClock == 360000) { /* G400 MAX */ 896fe5e51b7Smrg if(pMga->OverclockMem) { 897fe5e51b7Smrg /* 150/200 */ 898fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x05; 899fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x42; 900fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18; 901fe5e51b7Smrg pReg->Option3 = 0x019B8419; 902fe5e51b7Smrg pReg->Option = 0x50574120; 903fe5e51b7Smrg } else { 904fe5e51b7Smrg /* 125/166 */ 905fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x02; 906fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x1B; 907fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18; 908fe5e51b7Smrg pReg->Option3 = 0x019B8419; 909fe5e51b7Smrg pReg->Option = 0x5053C120; 910fe5e51b7Smrg } 911fe5e51b7Smrg } else { 912fe5e51b7Smrg if(pMga->OverclockMem) { 913fe5e51b7Smrg /* 125/166 */ 914fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x02; 915fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x1B; 916fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18; 917fe5e51b7Smrg pReg->Option3 = 0x019B8419; 918fe5e51b7Smrg pReg->Option = 0x5053C120; 919fe5e51b7Smrg } else { 920fe5e51b7Smrg /* 110/166 */ 921fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x13; 922fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x7A; 923fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x08; 924fe5e51b7Smrg pReg->Option3 = 0x0190a421; 925fe5e51b7Smrg pReg->Option = 0x50044120; 926fe5e51b7Smrg } 927fe5e51b7Smrg } 928fe5e51b7Smrg if(pMga->HasSDRAM) 929fe5e51b7Smrg pReg->Option &= ~(1 << 14); 930fe5e51b7Smrg pReg->Option2 = 0x01003000; 931fe5e51b7Smrg break; 932fe5e51b7Smrg case PCI_CHIP_MGAG200_SE_A_PCI: 933fe5e51b7Smrg case PCI_CHIP_MGAG200_SE_B_PCI: 934fe5e51b7Smrg#ifdef USEMGAHAL 935fe5e51b7Smrg MGA_HAL(break;); 936fe5e51b7Smrg#endif 937fe5e51b7Smrg pReg->DacRegs[ MGA1064_VREF_CTL ] = 0x03; 938fe5e51b7Smrg pReg->DacRegs[MGA1064_PIX_CLK_CTL] = 939fe5e51b7Smrg MGA1064_PIX_CLK_CTL_SEL_PLL; 940fe5e51b7Smrg 941fe5e51b7Smrg pReg->DacRegs[MGA1064_MISC_CTL] = 942fe5e51b7Smrg MGA1064_MISC_CTL_DAC_EN | 943fe5e51b7Smrg MGA1064_MISC_CTL_VGA8 | 944fe5e51b7Smrg MGA1064_MISC_CTL_DAC_RAM_CS; 945fe5e51b7Smrg 946fe5e51b7Smrg if (pMga->HasSDRAM) 947fe5e51b7Smrg pReg->Option = 0x40049120; 948fe5e51b7Smrg pReg->Option2 = 0x00008000; 949fe5e51b7Smrg break; 950eda3803bSmrg 951eda3803bSmrg case PCI_CHIP_MGAG200_WINBOND_PCI: 952eda3803bSmrg pReg->DacRegs[MGA1064_VREF_CTL] = 0x07; 953eda3803bSmrg pReg->Option = 0x41049120; 954eda3803bSmrg pReg->Option2 = 0x0000b000; 955eda3803bSmrg break; 956eda3803bSmrg 957eda3803bSmrg case PCI_CHIP_MGAG200_EV_PCI: 958eda3803bSmrg pReg->DacRegs[MGA1064_PIX_CLK_CTL] = 959eda3803bSmrg MGA1064_PIX_CLK_CTL_SEL_PLL; 960eda3803bSmrg 961eda3803bSmrg pReg->DacRegs[MGA1064_MISC_CTL] = 962eda3803bSmrg MGA1064_MISC_CTL_VGA8 | 963eda3803bSmrg MGA1064_MISC_CTL_DAC_RAM_CS; 964eda3803bSmrg 965eda3803bSmrg pReg->Option = 0x00000120; 966eda3803bSmrg pReg->Option2 = 0x0000b000; 967eda3803bSmrg break; 968eda3803bSmrg 969a31a186aSmrg case PCI_CHIP_MGAG200_EH_PCI: 970a31a186aSmrg pReg->DacRegs[MGA1064_MISC_CTL] = 971a31a186aSmrg MGA1064_MISC_CTL_VGA8 | 972a31a186aSmrg MGA1064_MISC_CTL_DAC_RAM_CS; 973a31a186aSmrg 974a31a186aSmrg pReg->Option = 0x00000120; 975a31a186aSmrg pReg->Option2 = 0x0000b000; 976a31a186aSmrg break; 977a31a186aSmrg 978fe5e51b7Smrg case PCI_CHIP_MGAG200: 979fe5e51b7Smrg case PCI_CHIP_MGAG200_PCI: 980fe5e51b7Smrg default: 981fe5e51b7Smrg#ifdef USEMGAHAL 982fe5e51b7Smrg MGA_HAL(break;); 983fe5e51b7Smrg#endif 984fe5e51b7Smrg if(pMga->OverclockMem) { 985fe5e51b7Smrg /* 143 Mhz */ 986fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x06; 987fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x24; 988fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x10; 989fe5e51b7Smrg } else { 990fe5e51b7Smrg /* 124 Mhz */ 991fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x04; 992fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x2D; 993fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x19; 994fe5e51b7Smrg } 995fe5e51b7Smrg pReg->Option2 = 0x00008000; 996fe5e51b7Smrg if(pMga->HasSDRAM) 997fe5e51b7Smrg pReg->Option = 0x40499121; 998fe5e51b7Smrg else 999fe5e51b7Smrg pReg->Option = 0x4049cd21; 1000fe5e51b7Smrg break; 1001fe5e51b7Smrg } 1002fe5e51b7Smrg 1003fe5e51b7Smrg MGA_NOT_HAL( 1004fe5e51b7Smrg /* must always have the pci retries on but rely on 1005fe5e51b7Smrg polling to keep them from occuring */ 1006fe5e51b7Smrg pReg->Option &= ~0x20000000; 1007fe5e51b7Smrg 1008fe5e51b7Smrg switch(pLayout->bitsPerPixel) 1009fe5e51b7Smrg { 1010fe5e51b7Smrg case 8: 1011fe5e51b7Smrg pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_8bits; 1012fe5e51b7Smrg break; 1013fe5e51b7Smrg case 16: 1014fe5e51b7Smrg pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_16bits; 1015fe5e51b7Smrg if ( (pLayout->weight.red == 5) && (pLayout->weight.green == 5) 1016fe5e51b7Smrg && (pLayout->weight.blue == 5) ) { 1017fe5e51b7Smrg pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_15bits; 1018fe5e51b7Smrg } 1019fe5e51b7Smrg break; 1020fe5e51b7Smrg case 24: 1021fe5e51b7Smrg pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_24bits; 1022fe5e51b7Smrg break; 1023fe5e51b7Smrg case 32: 1024eda3803bSmrg pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_32_24bits; 1025eda3803bSmrg break; 1026fe5e51b7Smrg default: 1027fe5e51b7Smrg FatalError("MGA: unsupported depth\n"); 1028fe5e51b7Smrg } 1029fe5e51b7Smrg ); /* MGA_NOT_HAL */ 1030fe5e51b7Smrg 1031fe5e51b7Smrg /* 1032fe5e51b7Smrg * This will initialize all of the generic VGA registers. 1033fe5e51b7Smrg */ 1034fe5e51b7Smrg if (!vgaHWInit(pScrn, mode)) 1035fe5e51b7Smrg return(FALSE); 1036fe5e51b7Smrg 1037fe5e51b7Smrg /* 1038fe5e51b7Smrg * Here all of the MGA registers get filled in. 1039fe5e51b7Smrg */ 1040fe5e51b7Smrg hd = (mode->CrtcHDisplay >> 3) - 1; 1041fe5e51b7Smrg hs = (mode->CrtcHSyncStart >> 3) - 1; 1042fe5e51b7Smrg he = (mode->CrtcHSyncEnd >> 3) - 1; 1043fe5e51b7Smrg ht = (mode->CrtcHTotal >> 3) - 1; 1044fe5e51b7Smrg vd = mode->CrtcVDisplay - 1; 1045fe5e51b7Smrg vs = mode->CrtcVSyncStart - 1; 1046fe5e51b7Smrg ve = mode->CrtcVSyncEnd - 1; 1047fe5e51b7Smrg vt = mode->CrtcVTotal - 2; 1048fe5e51b7Smrg 1049fe5e51b7Smrg /* HTOTAL & 0x7 equal to 0x6 in 8bpp or 0x4 in 24bpp causes strange 1050fe5e51b7Smrg * vertical stripes 1051fe5e51b7Smrg */ 1052fe5e51b7Smrg if((ht & 0x07) == 0x06 || (ht & 0x07) == 0x04) 1053fe5e51b7Smrg ht++; 1054fe5e51b7Smrg 1055fe5e51b7Smrg if (pLayout->bitsPerPixel == 24) 1056fe5e51b7Smrg wd = (pLayout->displayWidth * 3) >> (4 - BppShift); 1057fe5e51b7Smrg else 1058fe5e51b7Smrg wd = pLayout->displayWidth >> (4 - BppShift); 1059fe5e51b7Smrg 1060fe5e51b7Smrg pReg->ExtVga[0] = 0; 1061fe5e51b7Smrg pReg->ExtVga[5] = 0; 1062fe5e51b7Smrg 1063fe5e51b7Smrg if (mode->Flags & V_INTERLACE) 1064fe5e51b7Smrg { 1065fe5e51b7Smrg pReg->ExtVga[0] = 0x80; 1066fe5e51b7Smrg pReg->ExtVga[5] = (hs + he - ht) >> 1; 1067fe5e51b7Smrg wd <<= 1; 1068fe5e51b7Smrg vt &= 0xFFFE; 1069fe5e51b7Smrg } 1070fe5e51b7Smrg 1071fe5e51b7Smrg pReg->ExtVga[0] |= (wd & 0x300) >> 4; 1072fe5e51b7Smrg pReg->ExtVga[1] = (((ht - 4) & 0x100) >> 8) | 1073fe5e51b7Smrg ((hd & 0x100) >> 7) | 1074fe5e51b7Smrg ((hs & 0x100) >> 6) | 1075fe5e51b7Smrg (ht & 0x40); 1076fe5e51b7Smrg pReg->ExtVga[2] = ((vt & 0xc00) >> 10) | 1077fe5e51b7Smrg ((vd & 0x400) >> 8) | 1078fe5e51b7Smrg ((vd & 0xc00) >> 7) | 1079fe5e51b7Smrg ((vs & 0xc00) >> 5) | 1080fe5e51b7Smrg ((vd & 0x400) >> 3); /* linecomp */ 1081fe5e51b7Smrg if (pLayout->bitsPerPixel == 24) 1082fe5e51b7Smrg pReg->ExtVga[3] = (((1 << BppShift) * 3) - 1) | 0x80; 1083fe5e51b7Smrg else 1084fe5e51b7Smrg pReg->ExtVga[3] = ((1 << BppShift) - 1) | 0x80; 1085fe5e51b7Smrg 1086eda3803bSmrg pReg->ExtVga[4] = 0; 1087eda3803bSmrg 1088eda3803bSmrg if (pMga->is_G200WB){ 1089eda3803bSmrg pReg->ExtVga[1] |= 0x88; 1090eda3803bSmrg } 1091fe5e51b7Smrg 1092fe5e51b7Smrg pVga->CRTC[0] = ht - 4; 1093fe5e51b7Smrg pVga->CRTC[1] = hd; 1094fe5e51b7Smrg pVga->CRTC[2] = hd; 1095fe5e51b7Smrg pVga->CRTC[3] = (ht & 0x1F) | 0x80; 1096fe5e51b7Smrg pVga->CRTC[4] = hs; 1097fe5e51b7Smrg pVga->CRTC[5] = ((ht & 0x20) << 2) | (he & 0x1F); 1098fe5e51b7Smrg pVga->CRTC[6] = vt & 0xFF; 1099fe5e51b7Smrg pVga->CRTC[7] = ((vt & 0x100) >> 8 ) | 1100fe5e51b7Smrg ((vd & 0x100) >> 7 ) | 1101fe5e51b7Smrg ((vs & 0x100) >> 6 ) | 1102fe5e51b7Smrg ((vd & 0x100) >> 5 ) | 1103fe5e51b7Smrg ((vd & 0x100) >> 4 ) | /* linecomp */ 1104fe5e51b7Smrg ((vt & 0x200) >> 4 ) | 1105fe5e51b7Smrg ((vd & 0x200) >> 3 ) | 1106fe5e51b7Smrg ((vs & 0x200) >> 2 ); 1107fe5e51b7Smrg pVga->CRTC[9] = ((vd & 0x200) >> 4) | 1108fe5e51b7Smrg ((vd & 0x200) >> 3); /* linecomp */ 1109fe5e51b7Smrg pVga->CRTC[16] = vs & 0xFF; 1110fe5e51b7Smrg pVga->CRTC[17] = (ve & 0x0F) | 0x20; 1111fe5e51b7Smrg pVga->CRTC[18] = vd & 0xFF; 1112fe5e51b7Smrg pVga->CRTC[19] = wd & 0xFF; 1113fe5e51b7Smrg pVga->CRTC[21] = vd & 0xFF; 1114fe5e51b7Smrg pVga->CRTC[22] = (vt + 1) & 0xFF; 1115fe5e51b7Smrg pVga->CRTC[24] = vd & 0xFF; /* linecomp */ 1116fe5e51b7Smrg 1117fe5e51b7Smrg MGA_NOT_HAL(pReg->DacRegs[MGA1064_CURSOR_BASE_ADR_LOW] = pMga->FbCursorOffset >> 10); 1118fe5e51b7Smrg MGA_NOT_HAL(pReg->DacRegs[MGA1064_CURSOR_BASE_ADR_HI] = pMga->FbCursorOffset >> 18); 1119fe5e51b7Smrg 1120fe5e51b7Smrg if (pMga->SyncOnGreen) { 1121fe5e51b7Smrg MGA_NOT_HAL( 1122fe5e51b7Smrg pReg->DacRegs[MGA1064_GEN_CTL] &= 1123fe5e51b7Smrg ~MGA1064_GEN_CTL_SYNC_ON_GREEN_DIS; 1124fe5e51b7Smrg ); 1125fe5e51b7Smrg 1126fe5e51b7Smrg pReg->ExtVga[3] |= 0x40; 1127fe5e51b7Smrg } 1128fe5e51b7Smrg 1129fe5e51b7Smrg /* select external clock */ 1130fe5e51b7Smrg pVga->MiscOutReg |= 0x0C; 1131fe5e51b7Smrg 1132fe5e51b7Smrg MGA_NOT_HAL( 1133fe5e51b7Smrg if (mode->Flags & V_DBLSCAN) 1134fe5e51b7Smrg pVga->CRTC[9] |= 0x80; 1135fe5e51b7Smrg 1136fe5e51b7Smrg if(MGAISGx50(pMga)) { 1137fe5e51b7Smrg OUTREG(MGAREG_ZORG, 0); 1138fe5e51b7Smrg } 1139fe5e51b7Smrg 1140fe5e51b7Smrg MGAGSetPCLK(pScrn, mode->Clock); 1141fe5e51b7Smrg ); /* MGA_NOT_HAL */ 1142fe5e51b7Smrg 1143fe5e51b7Smrg /* This disables the VGA memory aperture */ 1144fe5e51b7Smrg pVga->MiscOutReg &= ~0x02; 1145fe5e51b7Smrg 1146fe5e51b7Smrg /* Urgh. Why do we define our own xMODEINFO structure instead 1147fe5e51b7Smrg * of just passing the blinkin' DisplayModePtr? If we're going to 1148fe5e51b7Smrg * just cut'n'paste routines from the HALlib, it would be better 1149fe5e51b7Smrg * just to strip the MacroVision stuff out of the HALlib and release 1150fe5e51b7Smrg * that, surely? 1151fe5e51b7Smrg */ 1152fe5e51b7Smrg /********************* Second Crtc programming **************/ 1153fe5e51b7Smrg /* Writing values to crtc2[] array */ 1154fe5e51b7Smrg if (pMga->SecondCrtc) 1155fe5e51b7Smrg { 1156fe5e51b7Smrg MGACRTC2Get(pScrn, &ModeInfo); 1157fe5e51b7Smrg MGACRTC2GetPitch(pScrn, &ModeInfo); 1158fe5e51b7Smrg MGACRTC2GetDisplayStart(pScrn, &ModeInfo,0,0,0); 1159fe5e51b7Smrg } 1160fe5e51b7Smrg 1161fe5e51b7Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN 1162fe5e51b7Smrg /* Disable byte-swapping for big-endian architectures - the XFree 1163fe5e51b7Smrg driver seems to like a little-endian framebuffer -ReneR */ 1164fe5e51b7Smrg /* pReg->Option |= 0x80000000; */ 1165fe5e51b7Smrg pReg->Option &= ~0x80000000; 1166fe5e51b7Smrg#endif 1167fe5e51b7Smrg 1168fe5e51b7Smrg return(TRUE); 1169fe5e51b7Smrg} 1170fe5e51b7Smrg 1171fe5e51b7Smrg/* 1172fe5e51b7Smrg * MGAGLoadPalette 1173fe5e51b7Smrg */ 1174fe5e51b7Smrg 1175fe5e51b7Smrgstatic void 1176fe5e51b7SmrgMGAPaletteLoadCallback(ScrnInfoPtr pScrn) 1177fe5e51b7Smrg{ 1178fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1179fe5e51b7Smrg MGAPaletteInfo *pal = pMga->palinfo; 1180fe5e51b7Smrg int i; 1181fe5e51b7Smrg 1182fe5e51b7Smrg while (!(INREG8(0x1FDA) & 0x08)); 1183fe5e51b7Smrg 1184fe5e51b7Smrg for(i = 0; i < 256; i++) { 1185fe5e51b7Smrg if(pal->update) { 1186fe5e51b7Smrg outMGAdreg(MGA1064_WADR_PAL, i); 1187fe5e51b7Smrg outMGAdreg(MGA1064_COL_PAL, pal->red); 1188fe5e51b7Smrg outMGAdreg(MGA1064_COL_PAL, pal->green); 1189fe5e51b7Smrg outMGAdreg(MGA1064_COL_PAL, pal->blue); 1190fe5e51b7Smrg pal->update = FALSE; 1191fe5e51b7Smrg } 1192fe5e51b7Smrg pal++; 1193fe5e51b7Smrg } 1194fe5e51b7Smrg pMga->PaletteLoadCallback = NULL; 1195fe5e51b7Smrg} 1196fe5e51b7Smrg 1197fe5e51b7Smrgvoid MGAGLoadPalette( 1198fe5e51b7Smrg ScrnInfoPtr pScrn, 1199fe5e51b7Smrg int numColors, 1200fe5e51b7Smrg int *indices, 1201fe5e51b7Smrg LOCO *colors, 1202fe5e51b7Smrg VisualPtr pVisual 1203fe5e51b7Smrg){ 1204fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1205fe5e51b7Smrg 1206fe5e51b7Smrg if(pMga->Chipset == PCI_CHIP_MGAG400 || pMga->Chipset == PCI_CHIP_MGAG550){ 1207fe5e51b7Smrg /* load them at the retrace in the block handler instead to 1208fe5e51b7Smrg work around some problems with static on the screen */ 1209fe5e51b7Smrg while(numColors--) { 1210fe5e51b7Smrg pMga->palinfo[*indices].update = TRUE; 1211fe5e51b7Smrg pMga->palinfo[*indices].red = colors[*indices].red; 1212fe5e51b7Smrg pMga->palinfo[*indices].green = colors[*indices].green; 1213fe5e51b7Smrg pMga->palinfo[*indices].blue = colors[*indices].blue; 1214fe5e51b7Smrg indices++; 1215fe5e51b7Smrg } 1216fe5e51b7Smrg pMga->PaletteLoadCallback = MGAPaletteLoadCallback; 1217fe5e51b7Smrg return; 1218fe5e51b7Smrg } else { 1219fe5e51b7Smrg while(numColors--) { 1220fe5e51b7Smrg outMGAdreg(MGA1064_WADR_PAL, *indices); 1221fe5e51b7Smrg outMGAdreg(MGA1064_COL_PAL, colors[*indices].red); 1222fe5e51b7Smrg outMGAdreg(MGA1064_COL_PAL, colors[*indices].green); 1223fe5e51b7Smrg outMGAdreg(MGA1064_COL_PAL, colors[*indices].blue); 1224fe5e51b7Smrg indices++; 1225fe5e51b7Smrg } 1226fe5e51b7Smrg } 1227fe5e51b7Smrg} 1228fe5e51b7Smrg 1229fe5e51b7Smrg/* 1230fe5e51b7Smrg * MGAGRestorePalette 1231fe5e51b7Smrg */ 1232fe5e51b7Smrg 1233fe5e51b7Smrgstatic void 1234fe5e51b7SmrgMGAGRestorePalette(ScrnInfoPtr pScrn, unsigned char* pntr) 1235fe5e51b7Smrg{ 1236fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1237fe5e51b7Smrg int i = 768; 1238fe5e51b7Smrg 1239fe5e51b7Smrg outMGAdreg(MGA1064_WADR_PAL, 0x00); 1240fe5e51b7Smrg while(i--) 1241fe5e51b7Smrg outMGAdreg(MGA1064_COL_PAL, *(pntr++)); 1242fe5e51b7Smrg} 1243fe5e51b7Smrg 1244fe5e51b7Smrg/* 1245fe5e51b7Smrg * MGAGSavePalette 1246fe5e51b7Smrg */ 1247fe5e51b7Smrgstatic void 1248fe5e51b7SmrgMGAGSavePalette(ScrnInfoPtr pScrn, unsigned char* pntr) 1249fe5e51b7Smrg{ 1250fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1251fe5e51b7Smrg int i = 768; 1252fe5e51b7Smrg 1253fe5e51b7Smrg outMGAdreg(MGA1064_RADR_PAL, 0x00); 1254fe5e51b7Smrg while(i--) 1255fe5e51b7Smrg *(pntr++) = inMGAdreg(MGA1064_COL_PAL); 1256fe5e51b7Smrg} 1257fe5e51b7Smrg 1258fe5e51b7Smrg/* 1259fe5e51b7Smrg * MGAGRestore 1260fe5e51b7Smrg * 1261fe5e51b7Smrg * This function restores a video mode. It basically writes out all of 1262fe5e51b7Smrg * the registers that have previously been saved. 1263fe5e51b7Smrg */ 1264fe5e51b7Smrgstatic void 1265fe5e51b7SmrgMGAGRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, MGARegPtr mgaReg, 1266fe5e51b7Smrg Bool restoreFonts) 1267fe5e51b7Smrg{ 1268fe5e51b7Smrg int i; 1269fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1270fe5e51b7Smrg CARD32 optionMask; 1271fe5e51b7Smrg 1272eda3803bSmrgMGA_NOT_HAL( 1273eda3803bSmrg if (pMga->is_G200WB) 1274eda3803bSmrg { 1275eda3803bSmrg MGAG200WBPrepareForModeSwitch(pScrn); 1276eda3803bSmrg } 1277eda3803bSmrg); 1278eda3803bSmrg 1279fe5e51b7Smrg /* 1280fe5e51b7Smrg * Pixel Clock needs to be restored regardless if we use 1281fe5e51b7Smrg * HALLib or not. HALlib doesn't do a good job restoring 1282fe5e51b7Smrg * VESA modes. MATROX: hint, hint. 1283fe5e51b7Smrg */ 1284fe5e51b7Smrg if (MGAISGx50(pMga) && mgaReg->Clock) { 1285fe5e51b7Smrg /* 1286fe5e51b7Smrg * With HALlib program only when restoring to console! 1287fe5e51b7Smrg * To test this we check for Clock == 0. 1288fe5e51b7Smrg */ 1289fe5e51b7Smrg MGAG450SetPLLFreq(pScrn, mgaReg->Clock); 1290fe5e51b7Smrg mgaReg->PIXPLLCSaved = FALSE; 1291fe5e51b7Smrg } 1292fe5e51b7Smrg 1293fe5e51b7Smrg if(!pMga->SecondCrtc) { 1294fe5e51b7Smrg /* Do not set the memory config for primary cards as it 1295fe5e51b7Smrg should be correct already. Only on little endian architectures 1296fe5e51b7Smrg since we need to modify the byteswap bit. -ReneR */ 1297fe5e51b7Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN 1298fe5e51b7Smrg optionMask = OPTION1_MASK; 1299fe5e51b7Smrg#else 1300fe5e51b7Smrg optionMask = (pMga->Primary) ? OPTION1_MASK_PRIMARY : OPTION1_MASK; 1301fe5e51b7Smrg#endif 1302fe5e51b7Smrg 1303fe5e51b7SmrgMGA_NOT_HAL( 1304fe5e51b7Smrg /* 1305fe5e51b7Smrg * Code is needed to get things back to bank zero. 1306fe5e51b7Smrg */ 1307fe5e51b7Smrg 1308fe5e51b7Smrg /* restore DAC registers 1309fe5e51b7Smrg * according to the docs we shouldn't write to reserved regs*/ 1310fe5e51b7Smrg for (i = 0; i < DACREGSIZE; i++) { 1311fe5e51b7Smrg if( (i <= 0x03) || 1312fe5e51b7Smrg (i == 0x07) || 1313fe5e51b7Smrg (i == 0x0b) || 1314fe5e51b7Smrg (i == 0x0f) || 1315fe5e51b7Smrg ((i >= 0x13) && (i <= 0x17)) || 1316fe5e51b7Smrg (i == 0x1b) || 1317fe5e51b7Smrg (i == 0x1c) || 1318fe5e51b7Smrg ((i >= 0x1f) && (i <= 0x29)) || 1319fe5e51b7Smrg ((i >= 0x30) && (i <= 0x37)) || 1320fe5e51b7Smrg (MGAISGx50(pMga) && !mgaReg->PIXPLLCSaved && 1321fe5e51b7Smrg ((i == 0x2c) || (i == 0x2d) || (i == 0x2e) || 1322fe5e51b7Smrg (i == 0x4c) || (i == 0x4d) || (i == 0x4e)))) 1323fe5e51b7Smrg continue; 1324fe5e51b7Smrg if (pMga->is_G200SE 1325fe5e51b7Smrg && ((i == 0x2C) || (i == 0x2D) || (i == 0x2E))) 1326fe5e51b7Smrg continue; 1327a31a186aSmrg if ( (pMga->is_G200EV || pMga->is_G200WB || pMga->is_G200EH) && 1328eda3803bSmrg (i >= 0x44) && (i <= 0x4E)) 1329eda3803bSmrg continue; 1330eda3803bSmrg 1331fe5e51b7Smrg outMGAdac(i, mgaReg->DacRegs[i]); 1332fe5e51b7Smrg } 1333fe5e51b7Smrg 1334fe5e51b7Smrg if (!MGAISGx50(pMga)) { 1335fe5e51b7Smrg /* restore pci_option register */ 1336fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS 1337fe5e51b7Smrg pci_device_cfg_write_bits(pMga->PciInfo, optionMask, 1338fe5e51b7Smrg mgaReg->Option, PCI_OPTION_REG); 1339fe5e51b7Smrg 1340fe5e51b7Smrg if (pMga->Chipset != PCI_CHIP_MGA1064) { 1341fe5e51b7Smrg pci_device_cfg_write_bits(pMga->PciInfo, OPTION2_MASK, 1342fe5e51b7Smrg mgaReg->Option2, PCI_MGA_OPTION2); 1343fe5e51b7Smrg 1344fe5e51b7Smrg if (pMga->Chipset == PCI_CHIP_MGAG400 1345fe5e51b7Smrg || pMga->Chipset == PCI_CHIP_MGAG550) { 1346fe5e51b7Smrg pci_device_cfg_write_bits(pMga->PciInfo, OPTION3_MASK, 1347fe5e51b7Smrg mgaReg->Option3, 1348fe5e51b7Smrg PCI_MGA_OPTION3); 1349fe5e51b7Smrg } 1350fe5e51b7Smrg } 1351fe5e51b7Smrg#else 1352fe5e51b7Smrg /* restore pci_option register */ 1353fe5e51b7Smrg pciSetBitsLong(pMga->PciTag, PCI_OPTION_REG, optionMask, 1354fe5e51b7Smrg mgaReg->Option); 1355fe5e51b7Smrg if (pMga->Chipset != PCI_CHIP_MGA1064) 1356fe5e51b7Smrg pciSetBitsLong(pMga->PciTag, PCI_MGA_OPTION2, OPTION2_MASK, 1357fe5e51b7Smrg mgaReg->Option2); 1358fe5e51b7Smrg if (pMga->Chipset == PCI_CHIP_MGAG400 || pMga->Chipset == PCI_CHIP_MGAG550) 1359fe5e51b7Smrg pciSetBitsLong(pMga->PciTag, PCI_MGA_OPTION3, OPTION3_MASK, 1360fe5e51b7Smrg mgaReg->Option3); 1361fe5e51b7Smrg#endif 1362fe5e51b7Smrg } 1363eda3803bSmrg 1364eda3803bSmrg if (pMga->is_G200EV) { 1365eda3803bSmrg MGAG200EVPIXPLLSET(pScrn, mgaReg); 1366eda3803bSmrg } else if (pMga->is_G200WB) { 1367eda3803bSmrg MGAG200WBPIXPLLSET(pScrn, mgaReg); 1368a31a186aSmrg } else if (pMga->is_G200EH) { 1369a31a186aSmrg MGAG200EHPIXPLLSET(pScrn, mgaReg); 1370eda3803bSmrg } 1371fe5e51b7Smrg); /* MGA_NOT_HAL */ 1372fe5e51b7Smrg#ifdef USEMGAHAL 1373fe5e51b7Smrg /* 1374fe5e51b7Smrg * Work around another bug in HALlib: it doesn't restore the 1375fe5e51b7Smrg * DAC width register correctly. MATROX: hint, hint. 1376fe5e51b7Smrg */ 1377fe5e51b7Smrg MGA_HAL( 1378fe5e51b7Smrg outMGAdac(MGA1064_MUL_CTL,mgaReg->DacRegs[0]); 1379fe5e51b7Smrg outMGAdac(MGA1064_MISC_CTL,mgaReg->DacRegs[1]); 1380fe5e51b7Smrg if (!MGAISGx50(pMga)) { 1381fe5e51b7Smrg outMGAdac(MGA1064_PIX_PLLC_M,mgaReg->DacRegs[2]); 1382fe5e51b7Smrg outMGAdac(MGA1064_PIX_PLLC_N,mgaReg->DacRegs[3]); 1383fe5e51b7Smrg outMGAdac(MGA1064_PIX_PLLC_P,mgaReg->DacRegs[4]); 1384fe5e51b7Smrg } 1385fe5e51b7Smrg ); 1386fe5e51b7Smrg#endif 1387fe5e51b7Smrg /* restore CRTCEXT regs */ 1388fe5e51b7Smrg for (i = 0; i < 6; i++) 1389fe5e51b7Smrg OUTREG16(MGAREG_CRTCEXT_INDEX, (mgaReg->ExtVga[i] << 8) | i); 1390fe5e51b7Smrg 1391fe5e51b7Smrg /* This handles restoring the generic VGA registers. */ 1392fe5e51b7Smrg if (pMga->is_G200SE) { 1393fe5e51b7Smrg MGAG200SERestoreMode(pScrn, vgaReg); 1394fe5e51b7Smrg if (restoreFonts) 1395fe5e51b7Smrg MGAG200SERestoreFonts(pScrn, vgaReg); 1396fe5e51b7Smrg } else { 1397fe5e51b7Smrg vgaHWRestore(pScrn, vgaReg, 1398fe5e51b7Smrg VGA_SR_MODE | (restoreFonts ? VGA_SR_FONTS : 0)); 1399fe5e51b7Smrg } 1400fe5e51b7Smrg MGAGRestorePalette(pScrn, vgaReg->DAC); 1401fe5e51b7Smrg 1402eda3803bSmrg 1403eda3803bSmrg if (pMga->is_G200EV) { 1404eda3803bSmrg OUTREG16(MGAREG_CRTCEXT_INDEX, 6); 1405eda3803bSmrg OUTREG16(MGAREG_CRTCEXT_DATA, 0); 1406eda3803bSmrg } 1407eda3803bSmrg 1408fe5e51b7Smrg /* 1409fe5e51b7Smrg * this is needed to properly restore start address 1410fe5e51b7Smrg */ 1411fe5e51b7Smrg OUTREG16(MGAREG_CRTCEXT_INDEX, (mgaReg->ExtVga[0] << 8) | 0); 1412eda3803bSmrg 1413eda3803bSmrgMGA_NOT_HAL( 1414eda3803bSmrg if (pMga->is_G200WB) 1415eda3803bSmrg { 1416eda3803bSmrg MGAG200WBRestoreFromModeSwitch(pScrn); 1417eda3803bSmrg } 1418eda3803bSmrg); 1419eda3803bSmrg 1420fe5e51b7Smrg } else { 1421fe5e51b7Smrg /* Second Crtc */ 1422fe5e51b7Smrg xMODEINFO ModeInfo; 1423fe5e51b7Smrg 1424fe5e51b7SmrgMGA_NOT_HAL( 1425fe5e51b7Smrg /* Enable Dual Head */ 1426fe5e51b7Smrg MGACRTC2Set(pScrn, &ModeInfo); 1427fe5e51b7Smrg MGAEnableSecondOutPut(pScrn, &ModeInfo); 1428fe5e51b7Smrg MGACRTC2SetPitch(pScrn, &ModeInfo); 1429fe5e51b7Smrg MGACRTC2SetDisplayStart(pScrn, &ModeInfo,0,0,0); 1430fe5e51b7Smrg 1431fe5e51b7Smrg for (i = 0x80; i <= 0xa0; i ++) { 1432fe5e51b7Smrg if (i== 0x8d) { 1433fe5e51b7Smrg i = 0x8f; 1434fe5e51b7Smrg continue; 1435fe5e51b7Smrg } 1436fe5e51b7Smrg outMGAdac(i, mgaReg->dac2[ i - 0x80]); 1437fe5e51b7Smrg } 1438eda3803bSmrg 1439fe5e51b7Smrg); /* MGA_NOT_HAL */ 1440fe5e51b7Smrg 1441fe5e51b7Smrg } 1442fe5e51b7Smrg 1443fe5e51b7Smrg#ifdef DEBUG 1444fe5e51b7Smrg ErrorF("Setting DAC:"); 1445fe5e51b7Smrg for (i=0; i<DACREGSIZE; i++) { 1446fe5e51b7Smrg#if 1 1447fe5e51b7Smrg if(!(i%16)) ErrorF("\n%02X: ",i); 1448fe5e51b7Smrg ErrorF("%02X ", mgaReg->DacRegs[i]); 1449fe5e51b7Smrg#else 1450fe5e51b7Smrg if(!(i%8)) ErrorF("\n%02X: ",i); 1451fe5e51b7Smrg ErrorF("0x%02X, ", mgaReg->DacRegs[i]); 1452fe5e51b7Smrg#endif 1453fe5e51b7Smrg } 1454fe5e51b7Smrg ErrorF("\nOPTION = %08lX\n", mgaReg->Option); 1455fe5e51b7Smrg ErrorF("OPTION2 = %08lX\n", mgaReg->Option2); 1456fe5e51b7Smrg ErrorF("CRTCEXT:"); 1457fe5e51b7Smrg for (i=0; i<6; i++) ErrorF(" %02X", mgaReg->ExtVga[i]); 1458fe5e51b7Smrg ErrorF("\n"); 1459fe5e51b7Smrg#endif 1460fe5e51b7Smrg 1461fe5e51b7Smrg} 1462fe5e51b7Smrg 1463fe5e51b7Smrg/* 1464fe5e51b7Smrg * MGAGSave 1465fe5e51b7Smrg * 1466fe5e51b7Smrg * This function saves the video state. 1467fe5e51b7Smrg */ 1468fe5e51b7Smrgstatic void 1469fe5e51b7SmrgMGAGSave(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, MGARegPtr mgaReg, 1470fe5e51b7Smrg Bool saveFonts) 1471fe5e51b7Smrg{ 1472fe5e51b7Smrg int i; 1473fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1474fe5e51b7Smrg 1475fe5e51b7Smrg /* 1476fe5e51b7Smrg * Pixel Clock needs to be restored regardless if we use 1477fe5e51b7Smrg * HALLib or not. HALlib doesn't do a good job restoring 1478fe5e51b7Smrg * VESA modes (s.o.). MATROX: hint, hint. 1479fe5e51b7Smrg */ 1480fe5e51b7Smrg if (MGAISGx50(pMga)) { 1481fe5e51b7Smrg mgaReg->Clock = MGAG450SavePLLFreq(pScrn); 1482fe5e51b7Smrg } 1483fe5e51b7Smrg 1484fe5e51b7Smrg if(pMga->SecondCrtc == TRUE) { 1485fe5e51b7Smrg for(i = 0x80; i < 0xa0; i++) 1486fe5e51b7Smrg mgaReg->dac2[i-0x80] = inMGAdac(i); 1487fe5e51b7Smrg 1488fe5e51b7Smrg return; 1489fe5e51b7Smrg } 1490fe5e51b7Smrg 1491fe5e51b7Smrg MGA_NOT_HAL( 1492fe5e51b7Smrg /* Allocate the DacRegs space if not done already */ 1493fe5e51b7Smrg if (mgaReg->DacRegs == NULL) { 1494fe5e51b7Smrg mgaReg->DacRegs = xnfcalloc(DACREGSIZE, 1); 1495fe5e51b7Smrg } 1496fe5e51b7Smrg ); /* MGA_NOT_HAL */ 1497fe5e51b7Smrg 1498fe5e51b7Smrg /* 1499fe5e51b7Smrg * Code is needed to get back to bank zero. 1500fe5e51b7Smrg */ 1501fe5e51b7Smrg OUTREG16(MGAREG_CRTCEXT_INDEX, 0x0004); 1502fe5e51b7Smrg 1503fe5e51b7Smrg /* 1504fe5e51b7Smrg * This function will handle creating the data structure and filling 1505fe5e51b7Smrg * in the generic VGA portion. 1506fe5e51b7Smrg */ 1507fe5e51b7Smrg if (pMga->is_G200SE) { 1508fe5e51b7Smrg MGAG200SESaveMode(pScrn, vgaReg); 1509fe5e51b7Smrg if (saveFonts) 1510fe5e51b7Smrg MGAG200SESaveFonts(pScrn, vgaReg); 1511fe5e51b7Smrg } else { 1512fe5e51b7Smrg vgaHWSave(pScrn, vgaReg, VGA_SR_MODE | 1513fe5e51b7Smrg (saveFonts ? VGA_SR_FONTS : 0)); 1514fe5e51b7Smrg } 1515fe5e51b7Smrg MGAGSavePalette(pScrn, vgaReg->DAC); 1516fe5e51b7Smrg /* 1517fe5e51b7Smrg * Work around another bug in HALlib: it doesn't restore the 1518fe5e51b7Smrg * DAC width register correctly. 1519fe5e51b7Smrg */ 1520fe5e51b7Smrg 1521fe5e51b7Smrg#ifdef USEMGAHAL 1522fe5e51b7Smrg /* 1523fe5e51b7Smrg * Work around another bug in HALlib: it doesn't restore the 1524fe5e51b7Smrg * DAC width register correctly (s.o.). MATROX: hint, hint. 1525fe5e51b7Smrg */ 1526fe5e51b7Smrg MGA_HAL( 1527fe5e51b7Smrg if (mgaReg->DacRegs == NULL) { 1528fe5e51b7Smrg mgaReg->DacRegs = xnfcalloc(MGAISGx50(pMga) ? 2 : 5, 1); 1529fe5e51b7Smrg } 1530fe5e51b7Smrg mgaReg->DacRegs[0] = inMGAdac(MGA1064_MUL_CTL); 1531fe5e51b7Smrg mgaReg->DacRegs[1] = inMGAdac(MGA1064_MISC_CTL); 1532fe5e51b7Smrg if (!MGAISGx50(pMga)) { 1533fe5e51b7Smrg mgaReg->DacRegs[2] = inMGAdac(MGA1064_PIX_PLLC_M); 1534fe5e51b7Smrg mgaReg->DacRegs[3] = inMGAdac(MGA1064_PIX_PLLC_N); 1535fe5e51b7Smrg mgaReg->DacRegs[4] = inMGAdac(MGA1064_PIX_PLLC_P); 1536fe5e51b7Smrg } 1537fe5e51b7Smrg ); 1538fe5e51b7Smrg#endif 1539fe5e51b7Smrg MGA_NOT_HAL( 1540fe5e51b7Smrg /* 1541fe5e51b7Smrg * The port I/O code necessary to read in the extended registers. 1542fe5e51b7Smrg */ 1543fe5e51b7Smrg for (i = 0; i < DACREGSIZE; i++) 1544fe5e51b7Smrg mgaReg->DacRegs[i] = inMGAdac(i); 1545fe5e51b7Smrg 1546eda3803bSmrg if (pMga->is_G200WB) { 1547eda3803bSmrg mgaReg->PllM = inMGAdac(MGA1064_WB_PIX_PLLC_M); 1548eda3803bSmrg mgaReg->PllN = inMGAdac(MGA1064_WB_PIX_PLLC_N); 1549eda3803bSmrg mgaReg->PllP = inMGAdac(MGA1064_WB_PIX_PLLC_P); 1550eda3803bSmrg } else if (pMga->is_G200EV) { 1551eda3803bSmrg mgaReg->PllM = inMGAdac(MGA1064_EV_PIX_PLLC_M); 1552eda3803bSmrg mgaReg->PllN = inMGAdac(MGA1064_EV_PIX_PLLC_N); 1553eda3803bSmrg mgaReg->PllP = inMGAdac(MGA1064_EV_PIX_PLLC_P); 1554a31a186aSmrg } else if (pMga->is_G200EH) { 1555a31a186aSmrg mgaReg->PllM = inMGAdac(MGA1064_EH_PIX_PLLC_M); 1556a31a186aSmrg mgaReg->PllN = inMGAdac(MGA1064_EH_PIX_PLLC_N); 1557a31a186aSmrg mgaReg->PllP = inMGAdac(MGA1064_EH_PIX_PLLC_P); 1558eda3803bSmrg } 1559eda3803bSmrg 1560fe5e51b7Smrg mgaReg->PIXPLLCSaved = TRUE; 1561fe5e51b7Smrg 1562fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS 1563fe5e51b7Smrg pci_device_cfg_read_u32(pMga->PciInfo, & mgaReg->Option, 1564fe5e51b7Smrg PCI_OPTION_REG); 1565fe5e51b7Smrg pci_device_cfg_read_u32(pMga->PciInfo, & mgaReg->Option2, 1566fe5e51b7Smrg PCI_MGA_OPTION2); 1567fe5e51b7Smrg#else 1568fe5e51b7Smrg mgaReg->Option = pciReadLong(pMga->PciTag, PCI_OPTION_REG); 1569fe5e51b7Smrg 1570fe5e51b7Smrg mgaReg->Option2 = pciReadLong(pMga->PciTag, PCI_MGA_OPTION2); 1571fe5e51b7Smrg#endif 1572fe5e51b7Smrg if (pMga->Chipset == PCI_CHIP_MGAG400 || pMga->Chipset == PCI_CHIP_MGAG550) 1573fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS 1574fe5e51b7Smrg pci_device_cfg_read_u32(pMga->PciInfo, & mgaReg->Option3, 1575fe5e51b7Smrg PCI_MGA_OPTION3); 1576fe5e51b7Smrg#else 1577fe5e51b7Smrg mgaReg->Option3 = pciReadLong(pMga->PciTag, PCI_MGA_OPTION3); 1578fe5e51b7Smrg#endif 1579fe5e51b7Smrg ); /* MGA_NOT_HAL */ 1580fe5e51b7Smrg 1581fe5e51b7Smrg for (i = 0; i < 6; i++) 1582fe5e51b7Smrg { 1583fe5e51b7Smrg OUTREG8(MGAREG_CRTCEXT_INDEX, i); 1584fe5e51b7Smrg mgaReg->ExtVga[i] = INREG8(MGAREG_CRTCEXT_DATA); 1585fe5e51b7Smrg } 1586fe5e51b7Smrg 1587fe5e51b7Smrg#ifdef DEBUG 1588fe5e51b7Smrg ErrorF("Saved values:\nDAC:"); 1589fe5e51b7Smrg for (i=0; i<DACREGSIZE; i++) { 1590fe5e51b7Smrg#if 1 1591fe5e51b7Smrg if(!(i%16)) ErrorF("\n%02X: ",i); 1592fe5e51b7Smrg ErrorF("%02X ", mgaReg->DacRegs[i]); 1593fe5e51b7Smrg#else 1594fe5e51b7Smrg if(!(i%8)) ErrorF("\n%02X: ",i); 1595fe5e51b7Smrg ErrorF("0x%02X, ", mgaReg->DacRegs[i]); 1596fe5e51b7Smrg#endif 1597fe5e51b7Smrg } 1598fe5e51b7Smrg ErrorF("\nOPTION = %08lX\n:", mgaReg->Option); 1599fe5e51b7Smrg ErrorF("OPTION2 = %08lX\nCRTCEXT:", mgaReg->Option2); 1600fe5e51b7Smrg for (i=0; i<6; i++) ErrorF(" %02X", mgaReg->ExtVga[i]); 1601fe5e51b7Smrg ErrorF("\n"); 1602fe5e51b7Smrg#endif 1603fe5e51b7Smrg} 1604fe5e51b7Smrg 1605fe5e51b7Smrg/**** 1606fe5e51b7Smrg *** HW Cursor 1607fe5e51b7Smrg */ 1608fe5e51b7Smrgstatic void 1609fe5e51b7SmrgMGAGLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src) 1610fe5e51b7Smrg{ 1611fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1612fe5e51b7Smrg CARD32 *dst = (CARD32*)(pMga->FbBase + pMga->FbCursorOffset); 1613fe5e51b7Smrg int i = 128; 1614fe5e51b7Smrg 1615fe5e51b7Smrg /* swap bytes in each line */ 1616fe5e51b7Smrg while( i-- ) { 1617fe5e51b7Smrg *dst++ = (src[4] << 24) | (src[5] << 16) | (src[6] << 8) | src[7]; 1618fe5e51b7Smrg *dst++ = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3]; 1619fe5e51b7Smrg src += 8; 1620fe5e51b7Smrg } 1621fe5e51b7Smrg} 1622fe5e51b7Smrg 1623fe5e51b7Smrgstatic void 1624fe5e51b7SmrgMGAGShowCursor(ScrnInfoPtr pScrn) 1625fe5e51b7Smrg{ 1626fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1627fe5e51b7Smrg /* Enable cursor - X-Windows mode */ 1628fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_CTL, 0x03); 1629fe5e51b7Smrg} 1630fe5e51b7Smrg 1631fe5e51b7Smrgstatic void 1632fe5e51b7SmrgMGAGShowCursorG100(ScrnInfoPtr pScrn) 1633fe5e51b7Smrg{ 1634fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1635fe5e51b7Smrg /* Enable cursor - X-Windows mode */ 1636fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_CTL, 0x01); 1637fe5e51b7Smrg} 1638fe5e51b7Smrg 1639fe5e51b7Smrgstatic void 1640fe5e51b7SmrgMGAGHideCursor(ScrnInfoPtr pScrn) 1641fe5e51b7Smrg{ 1642fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1643fe5e51b7Smrg /* Disable cursor */ 1644fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_CTL, 0x00); 1645fe5e51b7Smrg} 1646fe5e51b7Smrg 1647fe5e51b7Smrgstatic void 1648fe5e51b7SmrgMGAGSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) 1649fe5e51b7Smrg{ 1650fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1651fe5e51b7Smrg x += 64; 1652fe5e51b7Smrg y += 64; 1653fe5e51b7Smrg 1654fe5e51b7Smrg#ifdef USEMGAHAL 1655fe5e51b7Smrg MGA_HAL( 1656fe5e51b7Smrg x += pMga->HALGranularityOffX; 1657fe5e51b7Smrg y += pMga->HALGranularityOffY; 1658fe5e51b7Smrg ); 1659fe5e51b7Smrg#endif 1660fe5e51b7Smrg /* cursor update must never occurs during a retrace period (pp 4-160) */ 1661fe5e51b7Smrg while( INREG( MGAREG_Status ) & 0x08 ); 1662fe5e51b7Smrg 1663fe5e51b7Smrg /* Output position - "only" 12 bits of location documented */ 1664fe5e51b7Smrg OUTREG8( RAMDAC_OFFSET + MGA1064_CUR_XLOW, (x & 0xFF)); 1665fe5e51b7Smrg OUTREG8( RAMDAC_OFFSET + MGA1064_CUR_XHI, (x & 0xF00) >> 8); 1666fe5e51b7Smrg OUTREG8( RAMDAC_OFFSET + MGA1064_CUR_YLOW, (y & 0xFF)); 1667fe5e51b7Smrg OUTREG8( RAMDAC_OFFSET + MGA1064_CUR_YHI, (y & 0xF00) >> 8); 1668fe5e51b7Smrg} 1669fe5e51b7Smrg 1670fe5e51b7Smrg 1671fe5e51b7Smrgstatic void 1672fe5e51b7SmrgMGAGSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) 1673fe5e51b7Smrg{ 1674fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1675fe5e51b7Smrg 1676fe5e51b7Smrg /* Background color */ 1677fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL0_RED, (bg & 0x00FF0000) >> 16); 1678fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL0_GREEN, (bg & 0x0000FF00) >> 8); 1679fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL0_BLUE, (bg & 0x000000FF)); 1680fe5e51b7Smrg 1681fe5e51b7Smrg /* Foreground color */ 1682fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL1_RED, (fg & 0x00FF0000) >> 16); 1683fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL1_GREEN, (fg & 0x0000FF00) >> 8); 1684fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL1_BLUE, (fg & 0x000000FF)); 1685fe5e51b7Smrg} 1686fe5e51b7Smrg 1687fe5e51b7Smrgstatic void 1688fe5e51b7SmrgMGAGSetCursorColorsG100(ScrnInfoPtr pScrn, int bg, int fg) 1689fe5e51b7Smrg{ 1690fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1691fe5e51b7Smrg 1692fe5e51b7Smrg /* Background color */ 1693fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL1_RED, (bg & 0x00FF0000) >> 16); 1694fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL1_GREEN, (bg & 0x0000FF00) >> 8); 1695fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL1_BLUE, (bg & 0x000000FF)); 1696fe5e51b7Smrg 1697fe5e51b7Smrg /* Foreground color */ 1698fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL2_RED, (fg & 0x00FF0000) >> 16); 1699fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL2_GREEN, (fg & 0x0000FF00) >> 8); 1700fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL2_BLUE, (fg & 0x000000FF)); 1701fe5e51b7Smrg} 1702fe5e51b7Smrg 1703fe5e51b7Smrgstatic Bool 1704fe5e51b7SmrgMGAGUseHWCursor(ScreenPtr pScrn, CursorPtr pCurs) 1705fe5e51b7Smrg{ 1706fe5e51b7Smrg MGAPtr pMga = MGAPTR(xf86Screens[pScrn->myNum]); 1707fe5e51b7Smrg /* This needs to detect if its on the second dac */ 1708fe5e51b7Smrg if( XF86SCRNINFO(pScrn)->currentMode->Flags & V_DBLSCAN ) 1709fe5e51b7Smrg return FALSE; 1710fe5e51b7Smrg if( pMga->SecondCrtc == TRUE ) 1711fe5e51b7Smrg return FALSE; 1712fe5e51b7Smrg return TRUE; 1713fe5e51b7Smrg} 1714fe5e51b7Smrg 1715fe5e51b7Smrg 1716fe5e51b7Smrg/* 1717fe5e51b7Smrg * According to mga-1064g.pdf pp215-216 (4-179 & 4-180) the low bits of 1718fe5e51b7Smrg * XGENIODATA and XGENIOCTL are connected to the 4 DDC pins, but don't say 1719fe5e51b7Smrg * which VGA line is connected to each DDC pin, so I've had to guess. 1720fe5e51b7Smrg * 1721fe5e51b7Smrg * DDC1 support only requires DDC_SDA_MASK, 1722fe5e51b7Smrg * DDC2 support requires DDC_SDA_MASK and DDC_SCL_MASK 1723fe5e51b7Smrg * 1724fe5e51b7Smrg * If we want DDC on second head (P2) then we must use DDC2 protocol (I2C) 1725fe5e51b7Smrg * 1726fe5e51b7Smrg * Be careful, DDC1 and DDC2 refer to protocols, DDC_P1 and DDC_P2 refer to 1727fe5e51b7Smrg * DDC data coming in on which videoport on the card 1728fe5e51b7Smrg */ 1729eda3803bSmrg#define DDC_P1_SDA_MASK (1 << 1) 1730eda3803bSmrg#define DDC_P1_SCL_MASK (1 << 3) 1731eda3803bSmrg 1732eda3803bSmrgstatic const struct mgag_i2c_private { 1733eda3803bSmrg unsigned sda_mask; 1734eda3803bSmrg unsigned scl_mask; 1735eda3803bSmrg} i2c_priv[] = { 1736eda3803bSmrg { (1 << 1), (1 << 3) }, 1737eda3803bSmrg { (1 << 0), (1 << 2) }, 1738eda3803bSmrg { (1 << 4), (1 << 5) }, 1739eda3803bSmrg { (1 << 0), (1 << 1) }, /* G200SE, G200EV and G200WB I2C bits */ 1740a31a186aSmrg { (1 << 1), (1 << 0) }, /* G200EH I2C bits */ 1741eda3803bSmrg}; 1742eda3803bSmrg 1743fe5e51b7Smrg 1744fe5e51b7Smrgstatic unsigned int 1745fe5e51b7SmrgMGAG_ddc1Read(ScrnInfoPtr pScrn) 1746fe5e51b7Smrg{ 1747fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1748fe5e51b7Smrg unsigned char val; 1749eda3803bSmrg int i2c_index; 1750eda3803bSmrg 1751eda3803bSmrg if (pMga->is_G200SE || pMga->is_G200WB || pMga->is_G200EV) 1752eda3803bSmrg i2c_index = 3; 1753a31a186aSmrg else if (pMga->is_G200EH) 1754a31a186aSmrg i2c_index = 4; 1755eda3803bSmrg else 1756eda3803bSmrg i2c_index = 0; 1757eda3803bSmrg 1758eda3803bSmrg const struct mgag_i2c_private *p = & i2c_priv[i2c_index]; 1759eda3803bSmrg 1760fe5e51b7Smrg /* Define the SDA as an input */ 1761eda3803bSmrg outMGAdacmsk(MGA1064_GEN_IO_CTL, ~(p->scl_mask | p->sda_mask), 0); 1762fe5e51b7Smrg 1763fe5e51b7Smrg /* wait for Vsync */ 1764fe5e51b7Smrg if (pMga->is_G200SE) { 1765fe5e51b7Smrg usleep(4); 1766fe5e51b7Smrg } else { 1767fe5e51b7Smrg while( INREG( MGAREG_Status ) & 0x08 ); 1768fe5e51b7Smrg while( ! (INREG( MGAREG_Status ) & 0x08) ); 1769fe5e51b7Smrg } 1770fe5e51b7Smrg 1771fe5e51b7Smrg /* Get the result */ 1772eda3803bSmrg val = (inMGAdac(MGA1064_GEN_IO_DATA) & p->sda_mask); 1773fe5e51b7Smrg return val; 1774fe5e51b7Smrg} 1775fe5e51b7Smrg 1776fe5e51b7Smrgstatic void 1777eda3803bSmrgMGAG_I2CGetBits(I2CBusPtr b, int *clock, int *data) 1778fe5e51b7Smrg{ 1779fe5e51b7Smrg ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; 1780fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1781eda3803bSmrg const struct mgag_i2c_private *p = 1782eda3803bSmrg (struct mgag_i2c_private *) b->DriverPrivate.ptr; 1783fe5e51b7Smrg unsigned char val; 1784fe5e51b7Smrg 1785fe5e51b7Smrg /* Get the result. */ 1786fe5e51b7Smrg val = inMGAdac(MGA1064_GEN_IO_DATA); 1787fe5e51b7Smrg 1788eda3803bSmrg *clock = (val & p->scl_mask) != 0; 1789eda3803bSmrg *data = (val & p->sda_mask) != 0; 1790fe5e51b7Smrg#ifdef DEBUG 1791fe5e51b7Smrg ErrorF("MGAG_I2CGetBits(%p,...) val=0x%x, returns clock %d, data %d\n", b, val, *clock, *data); 1792fe5e51b7Smrg#endif 1793fe5e51b7Smrg} 1794fe5e51b7Smrg 1795fe5e51b7Smrg/* 1796fe5e51b7Smrg * ATTENTION! - the DATA and CLOCK lines need to be tri-stated when 1797fe5e51b7Smrg * high. Therefore turn off output driver for the line to set line 1798fe5e51b7Smrg * to high. High signal is maintained by a 15k Ohm pull-up resistor. 1799fe5e51b7Smrg */ 1800fe5e51b7Smrgstatic void 1801eda3803bSmrgMGAG_I2CPutBits(I2CBusPtr b, int clock, int data) 1802fe5e51b7Smrg{ 1803fe5e51b7Smrg ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; 1804fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1805eda3803bSmrg const struct mgag_i2c_private *p = 1806eda3803bSmrg (struct mgag_i2c_private *) b->DriverPrivate.ptr; 1807fe5e51b7Smrg unsigned char drv, val; 1808fe5e51b7Smrg 1809eda3803bSmrg val = (clock ? p->scl_mask : 0) | (data ? p->sda_mask : 0); 1810eda3803bSmrg drv = ((!clock) ? p->scl_mask : 0) | ((!data) ? p->sda_mask : 0); 1811fe5e51b7Smrg 1812fe5e51b7Smrg /* Write the values */ 1813eda3803bSmrg outMGAdacmsk(MGA1064_GEN_IO_CTL, ~(p->scl_mask | p->sda_mask) , drv); 1814eda3803bSmrg outMGAdacmsk(MGA1064_GEN_IO_DATA, ~(p->scl_mask | p->sda_mask) , val); 1815fe5e51b7Smrg#ifdef DEBUG 1816fe5e51b7Smrg ErrorF("MGAG_I2CPutBits(%p, %d, %d) val=0x%x\n", b, clock, data, val); 1817fe5e51b7Smrg#endif 1818fe5e51b7Smrg} 1819fe5e51b7Smrg 1820fe5e51b7Smrg 1821eda3803bSmrgstatic I2CBusPtr 1822eda3803bSmrgmgag_create_i2c_bus(const char *name, unsigned bus_index, unsigned scrn_index) 1823fe5e51b7Smrg{ 1824eda3803bSmrg I2CBusPtr I2CPtr = xf86CreateI2CBusRec(); 1825eda3803bSmrg 1826eda3803bSmrg if (I2CPtr != NULL) { 1827eda3803bSmrg I2CPtr->BusName = name; 1828eda3803bSmrg I2CPtr->scrnIndex = scrn_index; 1829eda3803bSmrg I2CPtr->I2CPutBits = MGAG_I2CPutBits; 1830eda3803bSmrg I2CPtr->I2CGetBits = MGAG_I2CGetBits; 1831eda3803bSmrg I2CPtr->AcknTimeout = 5; 1832eda3803bSmrg I2CPtr->DriverPrivate.ptr = & i2c_priv[bus_index]; 1833eda3803bSmrg 1834eda3803bSmrg if (!xf86I2CBusInit(I2CPtr)) { 1835eda3803bSmrg xf86DestroyI2CBusRec(I2CPtr, TRUE, TRUE); 1836eda3803bSmrg I2CPtr = NULL; 1837eda3803bSmrg } 1838eda3803bSmrg } 1839eda3803bSmrg 1840eda3803bSmrg return I2CPtr; 1841fe5e51b7Smrg} 1842fe5e51b7Smrg 1843eda3803bSmrg 1844fe5e51b7SmrgBool 1845fe5e51b7SmrgMGAG_i2cInit(ScrnInfoPtr pScrn) 1846fe5e51b7Smrg{ 1847fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1848fe5e51b7Smrg 1849fe5e51b7Smrg if (pMga->SecondCrtc == FALSE) { 1850eda3803bSmrg int i2c_index; 1851fe5e51b7Smrg 1852eda3803bSmrg if (pMga->is_G200SE || pMga->is_G200WB || pMga->is_G200EV) 1853eda3803bSmrg i2c_index = 3; 1854a31a186aSmrg else if (pMga->is_G200EH) 1855a31a186aSmrg i2c_index = 4; 1856eda3803bSmrg else 1857eda3803bSmrg i2c_index = 0; 1858fe5e51b7Smrg 1859eda3803bSmrg pMga->DDC_Bus1 = mgag_create_i2c_bus("DDC P1", 1860eda3803bSmrg i2c_index, pScrn->scrnIndex); 1861eda3803bSmrg return (pMga->DDC_Bus1 != NULL); 1862eda3803bSmrg } else { 1863eda3803bSmrg /* We have a dual head setup on G-series, set up DDC #2. */ 1864eda3803bSmrg pMga->DDC_Bus2 = mgag_create_i2c_bus("DDC P2", 1, pScrn->scrnIndex); 1865eda3803bSmrg 1866eda3803bSmrg if (pMga->DDC_Bus2 != NULL) { 1867eda3803bSmrg /* 0xA0 is DDC EEPROM address */ 1868eda3803bSmrg if (!xf86I2CProbeAddress(pMga->DDC_Bus2, 0xA0)) { 1869eda3803bSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "DDC #2 unavailable -> TV cable connected or no monitor connected!\n"); 1870eda3803bSmrg pMga->Crtc2IsTV = TRUE; /* assume for now. We need to fix HAL interactions. */ 1871fe5e51b7Smrg } 1872eda3803bSmrg } 1873fe5e51b7Smrg 1874fe5e51b7Smrg /* Then try to set up MAVEN bus. */ 1875eda3803bSmrg pMga->Maven_Bus = mgag_create_i2c_bus("MAVEN", 2, pScrn->scrnIndex); 1876eda3803bSmrg if (pMga->Maven_Bus != NULL) { 1877eda3803bSmrg pMga->Maven = NULL; 1878eda3803bSmrg pMga->Maven_Version = 0; 1879eda3803bSmrg 1880eda3803bSmrg /* Try to detect the MAVEN. */ 1881eda3803bSmrg if (xf86I2CProbeAddress(pMga->Maven_Bus, MAVEN_READ)) { 1882eda3803bSmrg I2CDevPtr dp = xf86CreateI2CDevRec(); 1883eda3803bSmrg if (dp) { 1884eda3803bSmrg I2CByte maven_ver; 1885eda3803bSmrg 1886eda3803bSmrg dp->DevName = "MGA-TVO"; 1887eda3803bSmrg dp->SlaveAddr = MAVEN_WRITE; 1888eda3803bSmrg dp->pI2CBus = pMga->Maven_Bus; 1889eda3803bSmrg if (!xf86I2CDevInit(dp)) { 1890eda3803bSmrg xf86DestroyI2CDevRec(dp, TRUE); 1891eda3803bSmrg } else { 1892eda3803bSmrg pMga->Maven = dp; 1893eda3803bSmrg if (MGAMavenRead(pScrn, 0xB2, &maven_ver)) { 1894eda3803bSmrg /* heuristic stolen from matroxfb */ 1895eda3803bSmrg pMga->Maven_Version = (maven_ver < 0x14) 1896eda3803bSmrg ? 'B' : 'C'; 1897eda3803bSmrg 1898eda3803bSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1899eda3803bSmrg "MAVEN revision MGA-TVO-%c detected (0x%x)\n", 1900eda3803bSmrg pMga->Maven_Version, maven_ver); 1901eda3803bSmrg } else { 1902eda3803bSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Failed to determine MAVEN hardware version!\n"); 1903fe5e51b7Smrg } 1904fe5e51b7Smrg } 1905eda3803bSmrg } 1906eda3803bSmrg } 1907fe5e51b7Smrg 1908eda3803bSmrg if (pMga->Maven == NULL) { 1909eda3803bSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1910eda3803bSmrg "Failed to register MGA-TVO I2C device!\n"); 1911fe5e51b7Smrg } 1912eda3803bSmrg } 1913fe5e51b7Smrg } 1914fe5e51b7Smrg 1915fe5e51b7Smrg return TRUE; 1916fe5e51b7Smrg} 1917fe5e51b7Smrg 1918fe5e51b7Smrg 1919fe5e51b7Smrg/* 1920fe5e51b7Smrg * MGAGRamdacInit 1921fe5e51b7Smrg * Handle broken G100 special. 1922fe5e51b7Smrg */ 1923fe5e51b7Smrgstatic void 1924fe5e51b7SmrgMGAGRamdacInit(ScrnInfoPtr pScrn) 1925fe5e51b7Smrg{ 1926fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1927fe5e51b7Smrg MGARamdacPtr MGAdac = &pMga->Dac; 1928fe5e51b7Smrg 1929fe5e51b7Smrg MGAdac->isHwCursor = TRUE; 1930fe5e51b7Smrg MGAdac->CursorOffscreenMemSize = 1024; 1931fe5e51b7Smrg MGAdac->CursorMaxWidth = 64; 1932fe5e51b7Smrg MGAdac->CursorMaxHeight = 64; 1933fe5e51b7Smrg MGAdac->SetCursorPosition = MGAGSetCursorPosition; 1934fe5e51b7Smrg MGAdac->LoadCursorImage = MGAGLoadCursorImage; 1935fe5e51b7Smrg MGAdac->HideCursor = MGAGHideCursor; 1936fe5e51b7Smrg if ((pMga->Chipset == PCI_CHIP_MGAG100) 1937fe5e51b7Smrg || (pMga->Chipset == PCI_CHIP_MGAG100)) { 1938fe5e51b7Smrg MGAdac->SetCursorColors = MGAGSetCursorColorsG100; 1939fe5e51b7Smrg MGAdac->ShowCursor = MGAGShowCursorG100; 1940fe5e51b7Smrg } else { 1941fe5e51b7Smrg MGAdac->SetCursorColors = MGAGSetCursorColors; 1942fe5e51b7Smrg MGAdac->ShowCursor = MGAGShowCursor; 1943fe5e51b7Smrg } 1944fe5e51b7Smrg MGAdac->UseHWCursor = MGAGUseHWCursor; 1945fe5e51b7Smrg MGAdac->CursorFlags = 1946fe5e51b7Smrg#if X_BYTE_ORDER == X_LITTLE_ENDIAN 1947fe5e51b7Smrg HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | 1948fe5e51b7Smrg#endif 1949fe5e51b7Smrg HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 | 1950fe5e51b7Smrg HARDWARE_CURSOR_TRUECOLOR_AT_8BPP; 1951fe5e51b7Smrg 1952fe5e51b7Smrg MGAdac->LoadPalette = MGAGLoadPalette; 1953fe5e51b7Smrg MGAdac->RestorePalette = MGAGRestorePalette; 1954fe5e51b7Smrg 1955fe5e51b7Smrg 1956fe5e51b7Smrg MGAdac->maxPixelClock = pMga->bios.pixel.max_freq; 1957fe5e51b7Smrg MGAdac->ClockFrom = X_PROBED; 1958fe5e51b7Smrg 1959fe5e51b7Smrg /* Disable interleaving and set the rounding value */ 1960fe5e51b7Smrg pMga->Interleave = FALSE; 1961fe5e51b7Smrg 1962fe5e51b7Smrg pMga->Roundings[0] = 64; 1963fe5e51b7Smrg pMga->Roundings[1] = 32; 1964fe5e51b7Smrg pMga->Roundings[2] = 64; 1965fe5e51b7Smrg pMga->Roundings[3] = 32; 1966fe5e51b7Smrg 1967fe5e51b7Smrg /* Clear Fast bitblt flag */ 1968fe5e51b7Smrg pMga->HasFBitBlt = FALSE; 1969fe5e51b7Smrg} 1970fe5e51b7Smrg 1971fe5e51b7Smrgvoid MGAGSetupFuncs(ScrnInfoPtr pScrn) 1972fe5e51b7Smrg{ 1973fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1974fe5e51b7Smrg 1975fe5e51b7Smrg pMga->PreInit = MGAGRamdacInit; 1976fe5e51b7Smrg pMga->Save = MGAGSave; 1977fe5e51b7Smrg pMga->Restore = MGAGRestore; 1978fe5e51b7Smrg pMga->ModeInit = MGAGInit; 1979a31a186aSmrg if (!pMga->is_G200WB){ 1980a31a186aSmrg pMga->ddc1Read = MGAG_ddc1Read; 1981a31a186aSmrg /* vgaHWddc1SetSpeed will only work if the card is in VGA mode */ 1982a31a186aSmrg pMga->DDC1SetSpeed = vgaHWddc1SetSpeedWeak(); 1983a31a186aSmrg } else { 1984a31a186aSmrg pMga->ddc1Read = NULL; 1985a31a186aSmrg pMga->DDC1SetSpeed = NULL; 1986a31a186aSmrg } 1987fe5e51b7Smrg pMga->i2cInit = MGAG_i2cInit; 1988fe5e51b7Smrg} 1989fe5e51b7Smrg 1990