mga_dacG.c revision fe5e51b7
1fe5e51b7Smrg/* 2fe5e51b7Smrg * MGA-1064, MGA-G100, MGA-G200, MGA-G400, MGA-G550 RAMDAC driver 3fe5e51b7Smrg */ 4fe5e51b7Smrg 5fe5e51b7Smrg/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/mga/mga_dacG.c,v 1.54tsi Exp $ */ 6fe5e51b7Smrg 7fe5e51b7Smrg/* 8fe5e51b7Smrg * This is a first cut at a non-accelerated version to work with the 9fe5e51b7Smrg * new server design (DHD). 10fe5e51b7Smrg */ 11fe5e51b7Smrg 12fe5e51b7Smrg#ifdef HAVE_CONFIG_H 13fe5e51b7Smrg#include "config.h" 14fe5e51b7Smrg#endif 15fe5e51b7Smrg 16fe5e51b7Smrg#include "colormapst.h" 17fe5e51b7Smrg 18fe5e51b7Smrg/* All drivers should typically include these */ 19fe5e51b7Smrg#include "xf86.h" 20fe5e51b7Smrg#include "xf86_OSproc.h" 21fe5e51b7Smrg 22fe5e51b7Smrg/* Drivers for PCI hardware need this */ 23fe5e51b7Smrg#include "xf86PciInfo.h" 24fe5e51b7Smrg 25fe5e51b7Smrg/* Drivers that need to access the PCI config space directly need this */ 26fe5e51b7Smrg#include "xf86Pci.h" 27fe5e51b7Smrg 28fe5e51b7Smrg#include "mga_reg.h" 29fe5e51b7Smrg#include "mga.h" 30fe5e51b7Smrg#include "mga_macros.h" 31fe5e51b7Smrg#include "mga_maven.h" 32fe5e51b7Smrg 33fe5e51b7Smrg#include "xf86DDC.h" 34fe5e51b7Smrg 35fe5e51b7Smrg#include <stdlib.h> 36fe5e51b7Smrg#include <unistd.h> 37fe5e51b7Smrg 38fe5e51b7Smrg/* 39fe5e51b7Smrg * implementation 40fe5e51b7Smrg */ 41fe5e51b7Smrg 42fe5e51b7Smrg#define DACREGSIZE 0x50 43fe5e51b7Smrg 44fe5e51b7Smrg/* 45fe5e51b7Smrg * Only change bits shown in this mask. Ideally reserved bits should be 46fe5e51b7Smrg * zeroed here. Also, don't change the vgaioen bit here since it is 47fe5e51b7Smrg * controlled elsewhere. 48fe5e51b7Smrg * 49fe5e51b7Smrg * XXX These settings need to be checked. 50fe5e51b7Smrg */ 51fe5e51b7Smrg#define OPTION1_MASK 0xFFFFFEFF 52fe5e51b7Smrg#define OPTION2_MASK 0xFFFFFFFF 53fe5e51b7Smrg#define OPTION3_MASK 0xFFFFFFFF 54fe5e51b7Smrg 55fe5e51b7Smrg#define OPTION1_MASK_PRIMARY 0xFFFC0FF 56fe5e51b7Smrg 57fe5e51b7Smrgstatic void MGAGRamdacInit(ScrnInfoPtr); 58fe5e51b7Smrgstatic void MGAGSave(ScrnInfoPtr, vgaRegPtr, MGARegPtr, Bool); 59fe5e51b7Smrgstatic void MGAGRestore(ScrnInfoPtr, vgaRegPtr, MGARegPtr, Bool); 60fe5e51b7Smrgstatic Bool MGAGInit(ScrnInfoPtr, DisplayModePtr); 61fe5e51b7Smrgstatic void MGAGLoadPalette(ScrnInfoPtr, int, int*, LOCO*, VisualPtr); 62fe5e51b7Smrgstatic Bool MGAG_i2cInit(ScrnInfoPtr pScrn); 63fe5e51b7Smrg 64fe5e51b7Smrgstatic void 65fe5e51b7SmrgMGAG200SEComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *M, int *N, int *P) 66fe5e51b7Smrg{ 67fe5e51b7Smrg unsigned int ulComputedFo; 68fe5e51b7Smrg unsigned int ulFDelta; 69fe5e51b7Smrg unsigned int ulFPermitedDelta; 70fe5e51b7Smrg unsigned int ulFTmpDelta; 71fe5e51b7Smrg unsigned int ulVCOMax, ulVCOMin; 72fe5e51b7Smrg unsigned int ulTestP; 73fe5e51b7Smrg unsigned int ulTestM; 74fe5e51b7Smrg unsigned int ulTestN; 75fe5e51b7Smrg unsigned int ulPLLFreqRef; 76fe5e51b7Smrg 77fe5e51b7Smrg ulVCOMax = 320000; 78fe5e51b7Smrg ulVCOMin = 160000; 79fe5e51b7Smrg ulPLLFreqRef = 25000; 80fe5e51b7Smrg 81fe5e51b7Smrg ulFDelta = 0xFFFFFFFF; 82fe5e51b7Smrg /* Permited delta is 0.5% as VESA Specification */ 83fe5e51b7Smrg ulFPermitedDelta = lFo * 5 / 1000; 84fe5e51b7Smrg 85fe5e51b7Smrg /* Then we need to minimize the M while staying within 0.5% */ 86fe5e51b7Smrg for (ulTestP = 8; ulTestP > 0; ulTestP >>= 1) { 87fe5e51b7Smrg if ((lFo * ulTestP) > ulVCOMax) continue; 88fe5e51b7Smrg if ((lFo * ulTestP) < ulVCOMin) continue; 89fe5e51b7Smrg 90fe5e51b7Smrg for (ulTestN = 17; ulTestN <= 256; ulTestN++) { 91fe5e51b7Smrg for (ulTestM = 1; ulTestM <= 32; ulTestM++) { 92fe5e51b7Smrg ulComputedFo = (ulPLLFreqRef * ulTestN) / (ulTestM * ulTestP); 93fe5e51b7Smrg if (ulComputedFo > lFo) 94fe5e51b7Smrg ulFTmpDelta = ulComputedFo - lFo; 95fe5e51b7Smrg else 96fe5e51b7Smrg ulFTmpDelta = lFo - ulComputedFo; 97fe5e51b7Smrg 98fe5e51b7Smrg if (ulFTmpDelta < ulFDelta) { 99fe5e51b7Smrg ulFDelta = ulFTmpDelta; 100fe5e51b7Smrg *M = ulTestM - 1; 101fe5e51b7Smrg *N = ulTestN - 1; 102fe5e51b7Smrg *P = ulTestP - 1; 103fe5e51b7Smrg } 104fe5e51b7Smrg } 105fe5e51b7Smrg } 106fe5e51b7Smrg } 107fe5e51b7Smrg} 108fe5e51b7Smrg 109fe5e51b7Smrg 110fe5e51b7Smrg/** 111fe5e51b7Smrg * Calculate the PLL settings (m, n, p, s). 112fe5e51b7Smrg * 113fe5e51b7Smrg * For more information, refer to the Matrox "MGA1064SG Developer 114fe5e51b7Smrg * Specification" (document 10524-MS-0100). chapter 5.7.8. "PLLs Clocks 115fe5e51b7Smrg * Generators" 116fe5e51b7Smrg * 117fe5e51b7Smrg * \param f_out Desired clock frequency, measured in kHz. 118fe5e51b7Smrg * \param best_m Value of PLL 'm' register. 119fe5e51b7Smrg * \param best_n Value of PLL 'n' register. 120fe5e51b7Smrg * \param p Value of PLL 'p' register. 121fe5e51b7Smrg * \param s Value of PLL 's' filter register (pix pll clock only). 122fe5e51b7Smrg */ 123fe5e51b7Smrg 124fe5e51b7Smrgstatic void 125fe5e51b7SmrgMGAGCalcClock ( ScrnInfoPtr pScrn, long f_out, 126fe5e51b7Smrg int *best_m, int *best_n, int *p, int *s ) 127fe5e51b7Smrg{ 128fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 129fe5e51b7Smrg int m, n; 130fe5e51b7Smrg double f_vco; 131fe5e51b7Smrg double m_err, calc_f; 132fe5e51b7Smrg const double ref_freq = (double) pMga->bios.pll_ref_freq; 133fe5e51b7Smrg const int feed_div_max = 127; 134fe5e51b7Smrg const int in_div_min = 1; 135fe5e51b7Smrg const int post_div_max = 7; 136fe5e51b7Smrg int feed_div_min; 137fe5e51b7Smrg int in_div_max; 138fe5e51b7Smrg 139fe5e51b7Smrg 140fe5e51b7Smrg switch( pMga->Chipset ) 141fe5e51b7Smrg { 142fe5e51b7Smrg case PCI_CHIP_MGA1064: 143fe5e51b7Smrg feed_div_min = 100; 144fe5e51b7Smrg in_div_max = 31; 145fe5e51b7Smrg break; 146fe5e51b7Smrg case PCI_CHIP_MGAG400: 147fe5e51b7Smrg case PCI_CHIP_MGAG550: 148fe5e51b7Smrg feed_div_min = 7; 149fe5e51b7Smrg in_div_max = 31; 150fe5e51b7Smrg break; 151fe5e51b7Smrg case PCI_CHIP_MGAG200_SE_A_PCI: 152fe5e51b7Smrg case PCI_CHIP_MGAG200_SE_B_PCI: 153fe5e51b7Smrg case PCI_CHIP_MGAG100: 154fe5e51b7Smrg case PCI_CHIP_MGAG100_PCI: 155fe5e51b7Smrg case PCI_CHIP_MGAG200: 156fe5e51b7Smrg case PCI_CHIP_MGAG200_PCI: 157fe5e51b7Smrg default: 158fe5e51b7Smrg feed_div_min = 7; 159fe5e51b7Smrg in_div_max = 6; 160fe5e51b7Smrg break; 161fe5e51b7Smrg } 162fe5e51b7Smrg 163fe5e51b7Smrg /* Make sure that f_min <= f_out */ 164fe5e51b7Smrg if ( f_out < ( pMga->bios.pixel.min_freq / 8)) 165fe5e51b7Smrg f_out = pMga->bios.pixel.min_freq / 8; 166fe5e51b7Smrg 167fe5e51b7Smrg /* 168fe5e51b7Smrg * f_pll = f_vco / (p+1) 169fe5e51b7Smrg * Choose p so that 170fe5e51b7Smrg * pMga->bios.pixel.min_freq <= f_vco <= pMga->bios.pixel.max_freq 171fe5e51b7Smrg * we don't have to bother checking for this maximum limit. 172fe5e51b7Smrg */ 173fe5e51b7Smrg f_vco = ( double ) f_out; 174fe5e51b7Smrg for ( *p = 0; *p <= post_div_max && f_vco < pMga->bios.pixel.min_freq; 175fe5e51b7Smrg *p = *p * 2 + 1, f_vco *= 2.0); 176fe5e51b7Smrg 177fe5e51b7Smrg /* Initial amount of error for frequency maximum */ 178fe5e51b7Smrg m_err = f_out; 179fe5e51b7Smrg 180fe5e51b7Smrg /* Search for the different values of ( m ) */ 181fe5e51b7Smrg for ( m = in_div_min ; m <= in_div_max ; m++ ) 182fe5e51b7Smrg { 183fe5e51b7Smrg /* see values of ( n ) which we can't use */ 184fe5e51b7Smrg for ( n = feed_div_min; n <= feed_div_max; n++ ) 185fe5e51b7Smrg { 186fe5e51b7Smrg calc_f = ref_freq * (n + 1) / (m + 1) ; 187fe5e51b7Smrg 188fe5e51b7Smrg /* 189fe5e51b7Smrg * Pick the closest frequency. 190fe5e51b7Smrg */ 191fe5e51b7Smrg if ( abs(calc_f - f_vco) < m_err ) { 192fe5e51b7Smrg m_err = abs(calc_f - f_vco); 193fe5e51b7Smrg *best_m = m; 194fe5e51b7Smrg *best_n = n; 195fe5e51b7Smrg } 196fe5e51b7Smrg } 197fe5e51b7Smrg } 198fe5e51b7Smrg 199fe5e51b7Smrg /* Now all the calculations can be completed */ 200fe5e51b7Smrg f_vco = ref_freq * (*best_n + 1) / (*best_m + 1); 201fe5e51b7Smrg 202fe5e51b7Smrg /* Adjustments for filtering pll feed back */ 203fe5e51b7Smrg if ( (50000.0 <= f_vco) 204fe5e51b7Smrg && (f_vco < 100000.0) ) 205fe5e51b7Smrg *s = 0; 206fe5e51b7Smrg if ( (100000.0 <= f_vco) 207fe5e51b7Smrg && (f_vco < 140000.0) ) 208fe5e51b7Smrg *s = 1; 209fe5e51b7Smrg if ( (140000.0 <= f_vco) 210fe5e51b7Smrg && (f_vco < 180000.0) ) 211fe5e51b7Smrg *s = 2; 212fe5e51b7Smrg if ( (180000.0 <= f_vco) ) 213fe5e51b7Smrg *s = 3; 214fe5e51b7Smrg 215fe5e51b7Smrg#ifdef DEBUG 216fe5e51b7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 217fe5e51b7Smrg "f_out_requ =%ld f_pll_real=%.1f f_vco=%.1f n=0x%x m=0x%x p=0x%x s=0x%x\n", 218fe5e51b7Smrg f_out, (f_vco / (*p + 1)), f_vco, *best_n, *best_m, *p, *s ); 219fe5e51b7Smrg#endif 220fe5e51b7Smrg} 221fe5e51b7Smrg 222fe5e51b7Smrg/* 223fe5e51b7Smrg * MGAGSetPCLK - Set the pixel (PCLK) clock. 224fe5e51b7Smrg */ 225fe5e51b7Smrgstatic void 226fe5e51b7SmrgMGAGSetPCLK( ScrnInfoPtr pScrn, long f_out ) 227fe5e51b7Smrg{ 228fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 229fe5e51b7Smrg MGARegPtr pReg = &pMga->ModeReg; 230fe5e51b7Smrg 231fe5e51b7Smrg /* Pixel clock values */ 232fe5e51b7Smrg int m, n, p, s; 233fe5e51b7Smrg 234fe5e51b7Smrg if(MGAISGx50(pMga)) { 235fe5e51b7Smrg pReg->Clock = f_out; 236fe5e51b7Smrg return; 237fe5e51b7Smrg } 238fe5e51b7Smrg 239fe5e51b7Smrg if (pMga->is_G200SE) { 240fe5e51b7Smrg MGAG200SEComputePLLParam(pScrn, f_out, &m, &n, &p); 241fe5e51b7Smrg 242fe5e51b7Smrg pReg->DacRegs[ MGA1064_PIX_PLLC_M ] = m; 243fe5e51b7Smrg pReg->DacRegs[ MGA1064_PIX_PLLC_N ] = n; 244fe5e51b7Smrg pReg->DacRegs[ MGA1064_PIX_PLLC_P ] = p; 245fe5e51b7Smrg } else { 246fe5e51b7Smrg /* Do the calculations for m, n, p and s */ 247fe5e51b7Smrg MGAGCalcClock( pScrn, f_out, &m, &n, &p, &s ); 248fe5e51b7Smrg 249fe5e51b7Smrg /* Values for the pixel clock PLL registers */ 250fe5e51b7Smrg pReg->DacRegs[ MGA1064_PIX_PLLC_M ] = m & 0x1F; 251fe5e51b7Smrg pReg->DacRegs[ MGA1064_PIX_PLLC_N ] = n & 0x7F; 252fe5e51b7Smrg pReg->DacRegs[ MGA1064_PIX_PLLC_P ] = (p & 0x07) | 253fe5e51b7Smrg ((s & 0x03) << 3); 254fe5e51b7Smrg } 255fe5e51b7Smrg} 256fe5e51b7Smrg 257fe5e51b7Smrg/* 258fe5e51b7Smrg * MGAGInit 259fe5e51b7Smrg */ 260fe5e51b7Smrgstatic Bool 261fe5e51b7SmrgMGAGInit(ScrnInfoPtr pScrn, DisplayModePtr mode) 262fe5e51b7Smrg{ 263fe5e51b7Smrg /* 264fe5e51b7Smrg * initial values of the DAC registers 265fe5e51b7Smrg */ 266fe5e51b7Smrg const static unsigned char initDAC[] = { 267fe5e51b7Smrg /* 0x00: */ 0, 0, 0, 0, 0, 0, 0x00, 0, 268fe5e51b7Smrg /* 0x08: */ 0, 0, 0, 0, 0, 0, 0, 0, 269fe5e51b7Smrg /* 0x10: */ 0, 0, 0, 0, 0, 0, 0, 0, 270fe5e51b7Smrg /* 0x18: */ 0x00, 0, 0xC9, 0xFF, 0xBF, 0x20, 0x1F, 0x20, 271fe5e51b7Smrg /* 0x20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 272fe5e51b7Smrg /* 0x28: */ 0x00, 0x00, 0x00, 0x00, 0, 0, 0, 0x40, 273fe5e51b7Smrg /* 0x30: */ 0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83, 274fe5e51b7Smrg /* 0x38: */ 0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A, 275fe5e51b7Smrg /* 0x40: */ 0, 0, 0, 0, 0, 0, 0, 0, 276fe5e51b7Smrg /* 0x48: */ 0, 0, 0, 0, 0, 0, 0, 0 277fe5e51b7Smrg }; 278fe5e51b7Smrg 279fe5e51b7Smrg int i; 280fe5e51b7Smrg int hd, hs, he, ht, vd, vs, ve, vt, wd; 281fe5e51b7Smrg int BppShift; 282fe5e51b7Smrg MGAPtr pMga; 283fe5e51b7Smrg MGARegPtr pReg; 284fe5e51b7Smrg vgaRegPtr pVga; 285fe5e51b7Smrg MGAFBLayout *pLayout; 286fe5e51b7Smrg xMODEINFO ModeInfo; 287fe5e51b7Smrg 288fe5e51b7Smrg ModeInfo.ulDispWidth = mode->HDisplay; 289fe5e51b7Smrg ModeInfo.ulDispHeight = mode->VDisplay; 290fe5e51b7Smrg ModeInfo.ulFBPitch = mode->HDisplay; 291fe5e51b7Smrg ModeInfo.ulBpp = pScrn->bitsPerPixel; 292fe5e51b7Smrg ModeInfo.flSignalMode = 0; 293fe5e51b7Smrg ModeInfo.ulPixClock = mode->Clock; 294fe5e51b7Smrg ModeInfo.ulHFPorch = mode->HSyncStart - mode->HDisplay; 295fe5e51b7Smrg ModeInfo.ulHSync = mode->HSyncEnd - mode->HSyncStart; 296fe5e51b7Smrg ModeInfo.ulHBPorch = mode->HTotal - mode->HSyncEnd; 297fe5e51b7Smrg ModeInfo.ulVFPorch = mode->VSyncStart - mode->VDisplay; 298fe5e51b7Smrg ModeInfo.ulVSync = mode->VSyncEnd - mode->VSyncStart; 299fe5e51b7Smrg ModeInfo.ulVBPorch = mode->VTotal - mode->VSyncEnd; 300fe5e51b7Smrg 301fe5e51b7Smrg pMga = MGAPTR(pScrn); 302fe5e51b7Smrg pReg = &pMga->ModeReg; 303fe5e51b7Smrg pVga = &VGAHWPTR(pScrn)->ModeReg; 304fe5e51b7Smrg pLayout = &pMga->CurrentLayout; 305fe5e51b7Smrg 306fe5e51b7Smrg BppShift = pMga->BppShifts[(pLayout->bitsPerPixel >> 3) - 1]; 307fe5e51b7Smrg 308fe5e51b7Smrg MGA_NOT_HAL( 309fe5e51b7Smrg /* Allocate the DacRegs space if not done already */ 310fe5e51b7Smrg if (pReg->DacRegs == NULL) { 311fe5e51b7Smrg pReg->DacRegs = xnfcalloc(DACREGSIZE, 1); 312fe5e51b7Smrg } 313fe5e51b7Smrg for (i = 0; i < DACREGSIZE; i++) { 314fe5e51b7Smrg pReg->DacRegs[i] = initDAC[i]; 315fe5e51b7Smrg } 316fe5e51b7Smrg ); /* MGA_NOT_HAL */ 317fe5e51b7Smrg 318fe5e51b7Smrg switch(pMga->Chipset) 319fe5e51b7Smrg { 320fe5e51b7Smrg case PCI_CHIP_MGA1064: 321fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x04; 322fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x44; 323fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18; 324fe5e51b7Smrg pReg->Option = 0x5F094F21; 325fe5e51b7Smrg pReg->Option2 = 0x00000000; 326fe5e51b7Smrg break; 327fe5e51b7Smrg case PCI_CHIP_MGAG100: 328fe5e51b7Smrg case PCI_CHIP_MGAG100_PCI: 329fe5e51b7Smrg pReg->DacRegs[MGA1064_VREF_CTL] = 0x03; 330fe5e51b7Smrg 331fe5e51b7Smrg if(pMga->HasSDRAM) { 332fe5e51b7Smrg if(pMga->OverclockMem) { 333fe5e51b7Smrg /* 220 Mhz */ 334fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x06; 335fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x38; 336fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18; 337fe5e51b7Smrg } else { 338fe5e51b7Smrg /* 203 Mhz */ 339fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x01; 340fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x0E; 341fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18; 342fe5e51b7Smrg } 343fe5e51b7Smrg pReg->Option = 0x404991a9; 344fe5e51b7Smrg } else { 345fe5e51b7Smrg if(pMga->OverclockMem) { 346fe5e51b7Smrg /* 143 Mhz */ 347fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x06; 348fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x24; 349fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x10; 350fe5e51b7Smrg } else { 351fe5e51b7Smrg /* 124 Mhz */ 352fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x04; 353fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x16; 354fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x08; 355fe5e51b7Smrg } 356fe5e51b7Smrg pReg->Option = 0x4049d121; 357fe5e51b7Smrg } 358fe5e51b7Smrg pReg->Option2 = 0x0000007; 359fe5e51b7Smrg break; 360fe5e51b7Smrg case PCI_CHIP_MGAG400: 361fe5e51b7Smrg case PCI_CHIP_MGAG550: 362fe5e51b7Smrg#ifdef USEMGAHAL 363fe5e51b7Smrg MGA_HAL(break;); 364fe5e51b7Smrg#endif 365fe5e51b7Smrg if (MGAISGx50(pMga)) 366fe5e51b7Smrg break; 367fe5e51b7Smrg 368fe5e51b7Smrg if(pMga->Dac.maxPixelClock == 360000) { /* G400 MAX */ 369fe5e51b7Smrg if(pMga->OverclockMem) { 370fe5e51b7Smrg /* 150/200 */ 371fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x05; 372fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x42; 373fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18; 374fe5e51b7Smrg pReg->Option3 = 0x019B8419; 375fe5e51b7Smrg pReg->Option = 0x50574120; 376fe5e51b7Smrg } else { 377fe5e51b7Smrg /* 125/166 */ 378fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x02; 379fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x1B; 380fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18; 381fe5e51b7Smrg pReg->Option3 = 0x019B8419; 382fe5e51b7Smrg pReg->Option = 0x5053C120; 383fe5e51b7Smrg } 384fe5e51b7Smrg } else { 385fe5e51b7Smrg if(pMga->OverclockMem) { 386fe5e51b7Smrg /* 125/166 */ 387fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x02; 388fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x1B; 389fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18; 390fe5e51b7Smrg pReg->Option3 = 0x019B8419; 391fe5e51b7Smrg pReg->Option = 0x5053C120; 392fe5e51b7Smrg } else { 393fe5e51b7Smrg /* 110/166 */ 394fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x13; 395fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x7A; 396fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x08; 397fe5e51b7Smrg pReg->Option3 = 0x0190a421; 398fe5e51b7Smrg pReg->Option = 0x50044120; 399fe5e51b7Smrg } 400fe5e51b7Smrg } 401fe5e51b7Smrg if(pMga->HasSDRAM) 402fe5e51b7Smrg pReg->Option &= ~(1 << 14); 403fe5e51b7Smrg pReg->Option2 = 0x01003000; 404fe5e51b7Smrg break; 405fe5e51b7Smrg case PCI_CHIP_MGAG200_SE_A_PCI: 406fe5e51b7Smrg case PCI_CHIP_MGAG200_SE_B_PCI: 407fe5e51b7Smrg#ifdef USEMGAHAL 408fe5e51b7Smrg MGA_HAL(break;); 409fe5e51b7Smrg#endif 410fe5e51b7Smrg pReg->DacRegs[ MGA1064_VREF_CTL ] = 0x03; 411fe5e51b7Smrg pReg->DacRegs[MGA1064_PIX_CLK_CTL] = 412fe5e51b7Smrg MGA1064_PIX_CLK_CTL_SEL_PLL; 413fe5e51b7Smrg 414fe5e51b7Smrg pReg->DacRegs[MGA1064_MISC_CTL] = 415fe5e51b7Smrg MGA1064_MISC_CTL_DAC_EN | 416fe5e51b7Smrg MGA1064_MISC_CTL_VGA8 | 417fe5e51b7Smrg MGA1064_MISC_CTL_DAC_RAM_CS; 418fe5e51b7Smrg 419fe5e51b7Smrg if (pMga->HasSDRAM) 420fe5e51b7Smrg pReg->Option = 0x40049120; 421fe5e51b7Smrg pReg->Option2 = 0x00008000; 422fe5e51b7Smrg break; 423fe5e51b7Smrg case PCI_CHIP_MGAG200: 424fe5e51b7Smrg case PCI_CHIP_MGAG200_PCI: 425fe5e51b7Smrg default: 426fe5e51b7Smrg#ifdef USEMGAHAL 427fe5e51b7Smrg MGA_HAL(break;); 428fe5e51b7Smrg#endif 429fe5e51b7Smrg if(pMga->OverclockMem) { 430fe5e51b7Smrg /* 143 Mhz */ 431fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x06; 432fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x24; 433fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x10; 434fe5e51b7Smrg } else { 435fe5e51b7Smrg /* 124 Mhz */ 436fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x04; 437fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x2D; 438fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x19; 439fe5e51b7Smrg } 440fe5e51b7Smrg pReg->Option2 = 0x00008000; 441fe5e51b7Smrg if(pMga->HasSDRAM) 442fe5e51b7Smrg pReg->Option = 0x40499121; 443fe5e51b7Smrg else 444fe5e51b7Smrg pReg->Option = 0x4049cd21; 445fe5e51b7Smrg break; 446fe5e51b7Smrg } 447fe5e51b7Smrg 448fe5e51b7Smrg MGA_NOT_HAL( 449fe5e51b7Smrg /* must always have the pci retries on but rely on 450fe5e51b7Smrg polling to keep them from occuring */ 451fe5e51b7Smrg pReg->Option &= ~0x20000000; 452fe5e51b7Smrg 453fe5e51b7Smrg switch(pLayout->bitsPerPixel) 454fe5e51b7Smrg { 455fe5e51b7Smrg case 8: 456fe5e51b7Smrg pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_8bits; 457fe5e51b7Smrg break; 458fe5e51b7Smrg case 16: 459fe5e51b7Smrg pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_16bits; 460fe5e51b7Smrg if ( (pLayout->weight.red == 5) && (pLayout->weight.green == 5) 461fe5e51b7Smrg && (pLayout->weight.blue == 5) ) { 462fe5e51b7Smrg pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_15bits; 463fe5e51b7Smrg } 464fe5e51b7Smrg break; 465fe5e51b7Smrg case 24: 466fe5e51b7Smrg pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_24bits; 467fe5e51b7Smrg break; 468fe5e51b7Smrg case 32: 469fe5e51b7Smrg if(pLayout->Overlay8Plus24) { 470fe5e51b7Smrg pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_32bits; 471fe5e51b7Smrg pReg->DacRegs[ MGA1064_COL_KEY_MSK_LSB ] = 0xFF; 472fe5e51b7Smrg pReg->DacRegs[ MGA1064_COL_KEY_LSB ] = pMga->colorKey; 473fe5e51b7Smrg } else 474fe5e51b7Smrg pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_32_24bits; 475fe5e51b7Smrg break; 476fe5e51b7Smrg default: 477fe5e51b7Smrg FatalError("MGA: unsupported depth\n"); 478fe5e51b7Smrg } 479fe5e51b7Smrg ); /* MGA_NOT_HAL */ 480fe5e51b7Smrg 481fe5e51b7Smrg /* 482fe5e51b7Smrg * This will initialize all of the generic VGA registers. 483fe5e51b7Smrg */ 484fe5e51b7Smrg if (!vgaHWInit(pScrn, mode)) 485fe5e51b7Smrg return(FALSE); 486fe5e51b7Smrg 487fe5e51b7Smrg /* 488fe5e51b7Smrg * Here all of the MGA registers get filled in. 489fe5e51b7Smrg */ 490fe5e51b7Smrg hd = (mode->CrtcHDisplay >> 3) - 1; 491fe5e51b7Smrg hs = (mode->CrtcHSyncStart >> 3) - 1; 492fe5e51b7Smrg he = (mode->CrtcHSyncEnd >> 3) - 1; 493fe5e51b7Smrg ht = (mode->CrtcHTotal >> 3) - 1; 494fe5e51b7Smrg vd = mode->CrtcVDisplay - 1; 495fe5e51b7Smrg vs = mode->CrtcVSyncStart - 1; 496fe5e51b7Smrg ve = mode->CrtcVSyncEnd - 1; 497fe5e51b7Smrg vt = mode->CrtcVTotal - 2; 498fe5e51b7Smrg 499fe5e51b7Smrg /* HTOTAL & 0x7 equal to 0x6 in 8bpp or 0x4 in 24bpp causes strange 500fe5e51b7Smrg * vertical stripes 501fe5e51b7Smrg */ 502fe5e51b7Smrg if((ht & 0x07) == 0x06 || (ht & 0x07) == 0x04) 503fe5e51b7Smrg ht++; 504fe5e51b7Smrg 505fe5e51b7Smrg if (pLayout->bitsPerPixel == 24) 506fe5e51b7Smrg wd = (pLayout->displayWidth * 3) >> (4 - BppShift); 507fe5e51b7Smrg else 508fe5e51b7Smrg wd = pLayout->displayWidth >> (4 - BppShift); 509fe5e51b7Smrg 510fe5e51b7Smrg pReg->ExtVga[0] = 0; 511fe5e51b7Smrg pReg->ExtVga[5] = 0; 512fe5e51b7Smrg 513fe5e51b7Smrg if (mode->Flags & V_INTERLACE) 514fe5e51b7Smrg { 515fe5e51b7Smrg pReg->ExtVga[0] = 0x80; 516fe5e51b7Smrg pReg->ExtVga[5] = (hs + he - ht) >> 1; 517fe5e51b7Smrg wd <<= 1; 518fe5e51b7Smrg vt &= 0xFFFE; 519fe5e51b7Smrg } 520fe5e51b7Smrg 521fe5e51b7Smrg pReg->ExtVga[0] |= (wd & 0x300) >> 4; 522fe5e51b7Smrg pReg->ExtVga[1] = (((ht - 4) & 0x100) >> 8) | 523fe5e51b7Smrg ((hd & 0x100) >> 7) | 524fe5e51b7Smrg ((hs & 0x100) >> 6) | 525fe5e51b7Smrg (ht & 0x40); 526fe5e51b7Smrg pReg->ExtVga[2] = ((vt & 0xc00) >> 10) | 527fe5e51b7Smrg ((vd & 0x400) >> 8) | 528fe5e51b7Smrg ((vd & 0xc00) >> 7) | 529fe5e51b7Smrg ((vs & 0xc00) >> 5) | 530fe5e51b7Smrg ((vd & 0x400) >> 3); /* linecomp */ 531fe5e51b7Smrg if (pLayout->bitsPerPixel == 24) 532fe5e51b7Smrg pReg->ExtVga[3] = (((1 << BppShift) * 3) - 1) | 0x80; 533fe5e51b7Smrg else 534fe5e51b7Smrg pReg->ExtVga[3] = ((1 << BppShift) - 1) | 0x80; 535fe5e51b7Smrg 536fe5e51b7Smrg pReg->ExtVga[4] = 0; 537fe5e51b7Smrg 538fe5e51b7Smrg pVga->CRTC[0] = ht - 4; 539fe5e51b7Smrg pVga->CRTC[1] = hd; 540fe5e51b7Smrg pVga->CRTC[2] = hd; 541fe5e51b7Smrg pVga->CRTC[3] = (ht & 0x1F) | 0x80; 542fe5e51b7Smrg pVga->CRTC[4] = hs; 543fe5e51b7Smrg pVga->CRTC[5] = ((ht & 0x20) << 2) | (he & 0x1F); 544fe5e51b7Smrg pVga->CRTC[6] = vt & 0xFF; 545fe5e51b7Smrg pVga->CRTC[7] = ((vt & 0x100) >> 8 ) | 546fe5e51b7Smrg ((vd & 0x100) >> 7 ) | 547fe5e51b7Smrg ((vs & 0x100) >> 6 ) | 548fe5e51b7Smrg ((vd & 0x100) >> 5 ) | 549fe5e51b7Smrg ((vd & 0x100) >> 4 ) | /* linecomp */ 550fe5e51b7Smrg ((vt & 0x200) >> 4 ) | 551fe5e51b7Smrg ((vd & 0x200) >> 3 ) | 552fe5e51b7Smrg ((vs & 0x200) >> 2 ); 553fe5e51b7Smrg pVga->CRTC[9] = ((vd & 0x200) >> 4) | 554fe5e51b7Smrg ((vd & 0x200) >> 3); /* linecomp */ 555fe5e51b7Smrg pVga->CRTC[16] = vs & 0xFF; 556fe5e51b7Smrg pVga->CRTC[17] = (ve & 0x0F) | 0x20; 557fe5e51b7Smrg pVga->CRTC[18] = vd & 0xFF; 558fe5e51b7Smrg pVga->CRTC[19] = wd & 0xFF; 559fe5e51b7Smrg pVga->CRTC[21] = vd & 0xFF; 560fe5e51b7Smrg pVga->CRTC[22] = (vt + 1) & 0xFF; 561fe5e51b7Smrg pVga->CRTC[24] = vd & 0xFF; /* linecomp */ 562fe5e51b7Smrg 563fe5e51b7Smrg MGA_NOT_HAL(pReg->DacRegs[MGA1064_CURSOR_BASE_ADR_LOW] = pMga->FbCursorOffset >> 10); 564fe5e51b7Smrg MGA_NOT_HAL(pReg->DacRegs[MGA1064_CURSOR_BASE_ADR_HI] = pMga->FbCursorOffset >> 18); 565fe5e51b7Smrg 566fe5e51b7Smrg if (pMga->SyncOnGreen) { 567fe5e51b7Smrg MGA_NOT_HAL( 568fe5e51b7Smrg pReg->DacRegs[MGA1064_GEN_CTL] &= 569fe5e51b7Smrg ~MGA1064_GEN_CTL_SYNC_ON_GREEN_DIS; 570fe5e51b7Smrg ); 571fe5e51b7Smrg 572fe5e51b7Smrg pReg->ExtVga[3] |= 0x40; 573fe5e51b7Smrg } 574fe5e51b7Smrg 575fe5e51b7Smrg /* select external clock */ 576fe5e51b7Smrg pVga->MiscOutReg |= 0x0C; 577fe5e51b7Smrg 578fe5e51b7Smrg MGA_NOT_HAL( 579fe5e51b7Smrg if (mode->Flags & V_DBLSCAN) 580fe5e51b7Smrg pVga->CRTC[9] |= 0x80; 581fe5e51b7Smrg 582fe5e51b7Smrg if(MGAISGx50(pMga)) { 583fe5e51b7Smrg OUTREG(MGAREG_ZORG, 0); 584fe5e51b7Smrg } 585fe5e51b7Smrg 586fe5e51b7Smrg MGAGSetPCLK(pScrn, mode->Clock); 587fe5e51b7Smrg ); /* MGA_NOT_HAL */ 588fe5e51b7Smrg 589fe5e51b7Smrg /* This disables the VGA memory aperture */ 590fe5e51b7Smrg pVga->MiscOutReg &= ~0x02; 591fe5e51b7Smrg 592fe5e51b7Smrg /* Urgh. Why do we define our own xMODEINFO structure instead 593fe5e51b7Smrg * of just passing the blinkin' DisplayModePtr? If we're going to 594fe5e51b7Smrg * just cut'n'paste routines from the HALlib, it would be better 595fe5e51b7Smrg * just to strip the MacroVision stuff out of the HALlib and release 596fe5e51b7Smrg * that, surely? 597fe5e51b7Smrg */ 598fe5e51b7Smrg /********************* Second Crtc programming **************/ 599fe5e51b7Smrg /* Writing values to crtc2[] array */ 600fe5e51b7Smrg if (pMga->SecondCrtc) 601fe5e51b7Smrg { 602fe5e51b7Smrg MGACRTC2Get(pScrn, &ModeInfo); 603fe5e51b7Smrg MGACRTC2GetPitch(pScrn, &ModeInfo); 604fe5e51b7Smrg MGACRTC2GetDisplayStart(pScrn, &ModeInfo,0,0,0); 605fe5e51b7Smrg } 606fe5e51b7Smrg 607fe5e51b7Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN 608fe5e51b7Smrg /* Disable byte-swapping for big-endian architectures - the XFree 609fe5e51b7Smrg driver seems to like a little-endian framebuffer -ReneR */ 610fe5e51b7Smrg /* pReg->Option |= 0x80000000; */ 611fe5e51b7Smrg pReg->Option &= ~0x80000000; 612fe5e51b7Smrg#endif 613fe5e51b7Smrg 614fe5e51b7Smrg return(TRUE); 615fe5e51b7Smrg} 616fe5e51b7Smrg 617fe5e51b7Smrg/* 618fe5e51b7Smrg * MGAGLoadPalette 619fe5e51b7Smrg */ 620fe5e51b7Smrg 621fe5e51b7Smrgstatic void 622fe5e51b7SmrgMGAPaletteLoadCallback(ScrnInfoPtr pScrn) 623fe5e51b7Smrg{ 624fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 625fe5e51b7Smrg MGAPaletteInfo *pal = pMga->palinfo; 626fe5e51b7Smrg int i; 627fe5e51b7Smrg 628fe5e51b7Smrg while (!(INREG8(0x1FDA) & 0x08)); 629fe5e51b7Smrg 630fe5e51b7Smrg for(i = 0; i < 256; i++) { 631fe5e51b7Smrg if(pal->update) { 632fe5e51b7Smrg outMGAdreg(MGA1064_WADR_PAL, i); 633fe5e51b7Smrg outMGAdreg(MGA1064_COL_PAL, pal->red); 634fe5e51b7Smrg outMGAdreg(MGA1064_COL_PAL, pal->green); 635fe5e51b7Smrg outMGAdreg(MGA1064_COL_PAL, pal->blue); 636fe5e51b7Smrg pal->update = FALSE; 637fe5e51b7Smrg } 638fe5e51b7Smrg pal++; 639fe5e51b7Smrg } 640fe5e51b7Smrg pMga->PaletteLoadCallback = NULL; 641fe5e51b7Smrg} 642fe5e51b7Smrg 643fe5e51b7Smrgvoid MGAGLoadPalette( 644fe5e51b7Smrg ScrnInfoPtr pScrn, 645fe5e51b7Smrg int numColors, 646fe5e51b7Smrg int *indices, 647fe5e51b7Smrg LOCO *colors, 648fe5e51b7Smrg VisualPtr pVisual 649fe5e51b7Smrg){ 650fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 651fe5e51b7Smrg 652fe5e51b7Smrg if((pMga->CurrentLayout.Overlay8Plus24) && (pVisual->nplanes != 8)) 653fe5e51b7Smrg return; 654fe5e51b7Smrg 655fe5e51b7Smrg if(pMga->Chipset == PCI_CHIP_MGAG400 || pMga->Chipset == PCI_CHIP_MGAG550){ 656fe5e51b7Smrg /* load them at the retrace in the block handler instead to 657fe5e51b7Smrg work around some problems with static on the screen */ 658fe5e51b7Smrg while(numColors--) { 659fe5e51b7Smrg pMga->palinfo[*indices].update = TRUE; 660fe5e51b7Smrg pMga->palinfo[*indices].red = colors[*indices].red; 661fe5e51b7Smrg pMga->palinfo[*indices].green = colors[*indices].green; 662fe5e51b7Smrg pMga->palinfo[*indices].blue = colors[*indices].blue; 663fe5e51b7Smrg indices++; 664fe5e51b7Smrg } 665fe5e51b7Smrg pMga->PaletteLoadCallback = MGAPaletteLoadCallback; 666fe5e51b7Smrg return; 667fe5e51b7Smrg } else { 668fe5e51b7Smrg while(numColors--) { 669fe5e51b7Smrg outMGAdreg(MGA1064_WADR_PAL, *indices); 670fe5e51b7Smrg outMGAdreg(MGA1064_COL_PAL, colors[*indices].red); 671fe5e51b7Smrg outMGAdreg(MGA1064_COL_PAL, colors[*indices].green); 672fe5e51b7Smrg outMGAdreg(MGA1064_COL_PAL, colors[*indices].blue); 673fe5e51b7Smrg indices++; 674fe5e51b7Smrg } 675fe5e51b7Smrg } 676fe5e51b7Smrg} 677fe5e51b7Smrg 678fe5e51b7Smrg/* 679fe5e51b7Smrg * MGAGRestorePalette 680fe5e51b7Smrg */ 681fe5e51b7Smrg 682fe5e51b7Smrgstatic void 683fe5e51b7SmrgMGAGRestorePalette(ScrnInfoPtr pScrn, unsigned char* pntr) 684fe5e51b7Smrg{ 685fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 686fe5e51b7Smrg int i = 768; 687fe5e51b7Smrg 688fe5e51b7Smrg outMGAdreg(MGA1064_WADR_PAL, 0x00); 689fe5e51b7Smrg while(i--) 690fe5e51b7Smrg outMGAdreg(MGA1064_COL_PAL, *(pntr++)); 691fe5e51b7Smrg} 692fe5e51b7Smrg 693fe5e51b7Smrg/* 694fe5e51b7Smrg * MGAGSavePalette 695fe5e51b7Smrg */ 696fe5e51b7Smrgstatic void 697fe5e51b7SmrgMGAGSavePalette(ScrnInfoPtr pScrn, unsigned char* pntr) 698fe5e51b7Smrg{ 699fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 700fe5e51b7Smrg int i = 768; 701fe5e51b7Smrg 702fe5e51b7Smrg outMGAdreg(MGA1064_RADR_PAL, 0x00); 703fe5e51b7Smrg while(i--) 704fe5e51b7Smrg *(pntr++) = inMGAdreg(MGA1064_COL_PAL); 705fe5e51b7Smrg} 706fe5e51b7Smrg 707fe5e51b7Smrg/* 708fe5e51b7Smrg * MGAGRestore 709fe5e51b7Smrg * 710fe5e51b7Smrg * This function restores a video mode. It basically writes out all of 711fe5e51b7Smrg * the registers that have previously been saved. 712fe5e51b7Smrg */ 713fe5e51b7Smrgstatic void 714fe5e51b7SmrgMGAGRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, MGARegPtr mgaReg, 715fe5e51b7Smrg Bool restoreFonts) 716fe5e51b7Smrg{ 717fe5e51b7Smrg int i; 718fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 719fe5e51b7Smrg CARD32 optionMask; 720fe5e51b7Smrg 721fe5e51b7Smrg /* 722fe5e51b7Smrg * Pixel Clock needs to be restored regardless if we use 723fe5e51b7Smrg * HALLib or not. HALlib doesn't do a good job restoring 724fe5e51b7Smrg * VESA modes. MATROX: hint, hint. 725fe5e51b7Smrg */ 726fe5e51b7Smrg if (MGAISGx50(pMga) && mgaReg->Clock) { 727fe5e51b7Smrg /* 728fe5e51b7Smrg * With HALlib program only when restoring to console! 729fe5e51b7Smrg * To test this we check for Clock == 0. 730fe5e51b7Smrg */ 731fe5e51b7Smrg MGAG450SetPLLFreq(pScrn, mgaReg->Clock); 732fe5e51b7Smrg mgaReg->PIXPLLCSaved = FALSE; 733fe5e51b7Smrg } 734fe5e51b7Smrg 735fe5e51b7Smrg if(!pMga->SecondCrtc) { 736fe5e51b7Smrg /* Do not set the memory config for primary cards as it 737fe5e51b7Smrg should be correct already. Only on little endian architectures 738fe5e51b7Smrg since we need to modify the byteswap bit. -ReneR */ 739fe5e51b7Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN 740fe5e51b7Smrg optionMask = OPTION1_MASK; 741fe5e51b7Smrg#else 742fe5e51b7Smrg optionMask = (pMga->Primary) ? OPTION1_MASK_PRIMARY : OPTION1_MASK; 743fe5e51b7Smrg#endif 744fe5e51b7Smrg 745fe5e51b7SmrgMGA_NOT_HAL( 746fe5e51b7Smrg /* 747fe5e51b7Smrg * Code is needed to get things back to bank zero. 748fe5e51b7Smrg */ 749fe5e51b7Smrg 750fe5e51b7Smrg /* restore DAC registers 751fe5e51b7Smrg * according to the docs we shouldn't write to reserved regs*/ 752fe5e51b7Smrg for (i = 0; i < DACREGSIZE; i++) { 753fe5e51b7Smrg if( (i <= 0x03) || 754fe5e51b7Smrg (i == 0x07) || 755fe5e51b7Smrg (i == 0x0b) || 756fe5e51b7Smrg (i == 0x0f) || 757fe5e51b7Smrg ((i >= 0x13) && (i <= 0x17)) || 758fe5e51b7Smrg (i == 0x1b) || 759fe5e51b7Smrg (i == 0x1c) || 760fe5e51b7Smrg ((i >= 0x1f) && (i <= 0x29)) || 761fe5e51b7Smrg ((i >= 0x30) && (i <= 0x37)) || 762fe5e51b7Smrg (MGAISGx50(pMga) && !mgaReg->PIXPLLCSaved && 763fe5e51b7Smrg ((i == 0x2c) || (i == 0x2d) || (i == 0x2e) || 764fe5e51b7Smrg (i == 0x4c) || (i == 0x4d) || (i == 0x4e)))) 765fe5e51b7Smrg continue; 766fe5e51b7Smrg if (pMga->is_G200SE 767fe5e51b7Smrg && ((i == 0x2C) || (i == 0x2D) || (i == 0x2E))) 768fe5e51b7Smrg continue; 769fe5e51b7Smrg outMGAdac(i, mgaReg->DacRegs[i]); 770fe5e51b7Smrg } 771fe5e51b7Smrg 772fe5e51b7Smrg if (!MGAISGx50(pMga)) { 773fe5e51b7Smrg /* restore pci_option register */ 774fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS 775fe5e51b7Smrg pci_device_cfg_write_bits(pMga->PciInfo, optionMask, 776fe5e51b7Smrg mgaReg->Option, PCI_OPTION_REG); 777fe5e51b7Smrg 778fe5e51b7Smrg if (pMga->Chipset != PCI_CHIP_MGA1064) { 779fe5e51b7Smrg pci_device_cfg_write_bits(pMga->PciInfo, OPTION2_MASK, 780fe5e51b7Smrg mgaReg->Option2, PCI_MGA_OPTION2); 781fe5e51b7Smrg 782fe5e51b7Smrg if (pMga->Chipset == PCI_CHIP_MGAG400 783fe5e51b7Smrg || pMga->Chipset == PCI_CHIP_MGAG550) { 784fe5e51b7Smrg pci_device_cfg_write_bits(pMga->PciInfo, OPTION3_MASK, 785fe5e51b7Smrg mgaReg->Option3, 786fe5e51b7Smrg PCI_MGA_OPTION3); 787fe5e51b7Smrg } 788fe5e51b7Smrg } 789fe5e51b7Smrg#else 790fe5e51b7Smrg /* restore pci_option register */ 791fe5e51b7Smrg pciSetBitsLong(pMga->PciTag, PCI_OPTION_REG, optionMask, 792fe5e51b7Smrg mgaReg->Option); 793fe5e51b7Smrg if (pMga->Chipset != PCI_CHIP_MGA1064) 794fe5e51b7Smrg pciSetBitsLong(pMga->PciTag, PCI_MGA_OPTION2, OPTION2_MASK, 795fe5e51b7Smrg mgaReg->Option2); 796fe5e51b7Smrg if (pMga->Chipset == PCI_CHIP_MGAG400 || pMga->Chipset == PCI_CHIP_MGAG550) 797fe5e51b7Smrg pciSetBitsLong(pMga->PciTag, PCI_MGA_OPTION3, OPTION3_MASK, 798fe5e51b7Smrg mgaReg->Option3); 799fe5e51b7Smrg#endif 800fe5e51b7Smrg } 801fe5e51b7Smrg); /* MGA_NOT_HAL */ 802fe5e51b7Smrg#ifdef USEMGAHAL 803fe5e51b7Smrg /* 804fe5e51b7Smrg * Work around another bug in HALlib: it doesn't restore the 805fe5e51b7Smrg * DAC width register correctly. MATROX: hint, hint. 806fe5e51b7Smrg */ 807fe5e51b7Smrg MGA_HAL( 808fe5e51b7Smrg outMGAdac(MGA1064_MUL_CTL,mgaReg->DacRegs[0]); 809fe5e51b7Smrg outMGAdac(MGA1064_MISC_CTL,mgaReg->DacRegs[1]); 810fe5e51b7Smrg if (!MGAISGx50(pMga)) { 811fe5e51b7Smrg outMGAdac(MGA1064_PIX_PLLC_M,mgaReg->DacRegs[2]); 812fe5e51b7Smrg outMGAdac(MGA1064_PIX_PLLC_N,mgaReg->DacRegs[3]); 813fe5e51b7Smrg outMGAdac(MGA1064_PIX_PLLC_P,mgaReg->DacRegs[4]); 814fe5e51b7Smrg } 815fe5e51b7Smrg ); 816fe5e51b7Smrg#endif 817fe5e51b7Smrg /* restore CRTCEXT regs */ 818fe5e51b7Smrg for (i = 0; i < 6; i++) 819fe5e51b7Smrg OUTREG16(MGAREG_CRTCEXT_INDEX, (mgaReg->ExtVga[i] << 8) | i); 820fe5e51b7Smrg 821fe5e51b7Smrg /* This handles restoring the generic VGA registers. */ 822fe5e51b7Smrg if (pMga->is_G200SE) { 823fe5e51b7Smrg MGAG200SERestoreMode(pScrn, vgaReg); 824fe5e51b7Smrg if (restoreFonts) 825fe5e51b7Smrg MGAG200SERestoreFonts(pScrn, vgaReg); 826fe5e51b7Smrg } else { 827fe5e51b7Smrg vgaHWRestore(pScrn, vgaReg, 828fe5e51b7Smrg VGA_SR_MODE | (restoreFonts ? VGA_SR_FONTS : 0)); 829fe5e51b7Smrg } 830fe5e51b7Smrg MGAGRestorePalette(pScrn, vgaReg->DAC); 831fe5e51b7Smrg 832fe5e51b7Smrg /* 833fe5e51b7Smrg * this is needed to properly restore start address 834fe5e51b7Smrg */ 835fe5e51b7Smrg OUTREG16(MGAREG_CRTCEXT_INDEX, (mgaReg->ExtVga[0] << 8) | 0); 836fe5e51b7Smrg } else { 837fe5e51b7Smrg /* Second Crtc */ 838fe5e51b7Smrg xMODEINFO ModeInfo; 839fe5e51b7Smrg 840fe5e51b7SmrgMGA_NOT_HAL( 841fe5e51b7Smrg /* Enable Dual Head */ 842fe5e51b7Smrg MGACRTC2Set(pScrn, &ModeInfo); 843fe5e51b7Smrg MGAEnableSecondOutPut(pScrn, &ModeInfo); 844fe5e51b7Smrg MGACRTC2SetPitch(pScrn, &ModeInfo); 845fe5e51b7Smrg MGACRTC2SetDisplayStart(pScrn, &ModeInfo,0,0,0); 846fe5e51b7Smrg 847fe5e51b7Smrg for (i = 0x80; i <= 0xa0; i ++) { 848fe5e51b7Smrg if (i== 0x8d) { 849fe5e51b7Smrg i = 0x8f; 850fe5e51b7Smrg continue; 851fe5e51b7Smrg } 852fe5e51b7Smrg outMGAdac(i, mgaReg->dac2[ i - 0x80]); 853fe5e51b7Smrg } 854fe5e51b7Smrg); /* MGA_NOT_HAL */ 855fe5e51b7Smrg 856fe5e51b7Smrg } 857fe5e51b7Smrg 858fe5e51b7Smrg#ifdef DEBUG 859fe5e51b7Smrg ErrorF("Setting DAC:"); 860fe5e51b7Smrg for (i=0; i<DACREGSIZE; i++) { 861fe5e51b7Smrg#if 1 862fe5e51b7Smrg if(!(i%16)) ErrorF("\n%02X: ",i); 863fe5e51b7Smrg ErrorF("%02X ", mgaReg->DacRegs[i]); 864fe5e51b7Smrg#else 865fe5e51b7Smrg if(!(i%8)) ErrorF("\n%02X: ",i); 866fe5e51b7Smrg ErrorF("0x%02X, ", mgaReg->DacRegs[i]); 867fe5e51b7Smrg#endif 868fe5e51b7Smrg } 869fe5e51b7Smrg ErrorF("\nOPTION = %08lX\n", mgaReg->Option); 870fe5e51b7Smrg ErrorF("OPTION2 = %08lX\n", mgaReg->Option2); 871fe5e51b7Smrg ErrorF("CRTCEXT:"); 872fe5e51b7Smrg for (i=0; i<6; i++) ErrorF(" %02X", mgaReg->ExtVga[i]); 873fe5e51b7Smrg ErrorF("\n"); 874fe5e51b7Smrg#endif 875fe5e51b7Smrg 876fe5e51b7Smrg} 877fe5e51b7Smrg 878fe5e51b7Smrg/* 879fe5e51b7Smrg * MGAGSave 880fe5e51b7Smrg * 881fe5e51b7Smrg * This function saves the video state. 882fe5e51b7Smrg */ 883fe5e51b7Smrgstatic void 884fe5e51b7SmrgMGAGSave(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, MGARegPtr mgaReg, 885fe5e51b7Smrg Bool saveFonts) 886fe5e51b7Smrg{ 887fe5e51b7Smrg int i; 888fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 889fe5e51b7Smrg 890fe5e51b7Smrg /* 891fe5e51b7Smrg * Pixel Clock needs to be restored regardless if we use 892fe5e51b7Smrg * HALLib or not. HALlib doesn't do a good job restoring 893fe5e51b7Smrg * VESA modes (s.o.). MATROX: hint, hint. 894fe5e51b7Smrg */ 895fe5e51b7Smrg if (MGAISGx50(pMga)) { 896fe5e51b7Smrg mgaReg->Clock = MGAG450SavePLLFreq(pScrn); 897fe5e51b7Smrg } 898fe5e51b7Smrg 899fe5e51b7Smrg if(pMga->SecondCrtc == TRUE) { 900fe5e51b7Smrg for(i = 0x80; i < 0xa0; i++) 901fe5e51b7Smrg mgaReg->dac2[i-0x80] = inMGAdac(i); 902fe5e51b7Smrg 903fe5e51b7Smrg return; 904fe5e51b7Smrg } 905fe5e51b7Smrg 906fe5e51b7Smrg MGA_NOT_HAL( 907fe5e51b7Smrg /* Allocate the DacRegs space if not done already */ 908fe5e51b7Smrg if (mgaReg->DacRegs == NULL) { 909fe5e51b7Smrg mgaReg->DacRegs = xnfcalloc(DACREGSIZE, 1); 910fe5e51b7Smrg } 911fe5e51b7Smrg ); /* MGA_NOT_HAL */ 912fe5e51b7Smrg 913fe5e51b7Smrg /* 914fe5e51b7Smrg * Code is needed to get back to bank zero. 915fe5e51b7Smrg */ 916fe5e51b7Smrg OUTREG16(MGAREG_CRTCEXT_INDEX, 0x0004); 917fe5e51b7Smrg 918fe5e51b7Smrg /* 919fe5e51b7Smrg * This function will handle creating the data structure and filling 920fe5e51b7Smrg * in the generic VGA portion. 921fe5e51b7Smrg */ 922fe5e51b7Smrg if (pMga->is_G200SE) { 923fe5e51b7Smrg MGAG200SESaveMode(pScrn, vgaReg); 924fe5e51b7Smrg if (saveFonts) 925fe5e51b7Smrg MGAG200SESaveFonts(pScrn, vgaReg); 926fe5e51b7Smrg } else { 927fe5e51b7Smrg vgaHWSave(pScrn, vgaReg, VGA_SR_MODE | 928fe5e51b7Smrg (saveFonts ? VGA_SR_FONTS : 0)); 929fe5e51b7Smrg } 930fe5e51b7Smrg MGAGSavePalette(pScrn, vgaReg->DAC); 931fe5e51b7Smrg /* 932fe5e51b7Smrg * Work around another bug in HALlib: it doesn't restore the 933fe5e51b7Smrg * DAC width register correctly. 934fe5e51b7Smrg */ 935fe5e51b7Smrg 936fe5e51b7Smrg#ifdef USEMGAHAL 937fe5e51b7Smrg /* 938fe5e51b7Smrg * Work around another bug in HALlib: it doesn't restore the 939fe5e51b7Smrg * DAC width register correctly (s.o.). MATROX: hint, hint. 940fe5e51b7Smrg */ 941fe5e51b7Smrg MGA_HAL( 942fe5e51b7Smrg if (mgaReg->DacRegs == NULL) { 943fe5e51b7Smrg mgaReg->DacRegs = xnfcalloc(MGAISGx50(pMga) ? 2 : 5, 1); 944fe5e51b7Smrg } 945fe5e51b7Smrg mgaReg->DacRegs[0] = inMGAdac(MGA1064_MUL_CTL); 946fe5e51b7Smrg mgaReg->DacRegs[1] = inMGAdac(MGA1064_MISC_CTL); 947fe5e51b7Smrg if (!MGAISGx50(pMga)) { 948fe5e51b7Smrg mgaReg->DacRegs[2] = inMGAdac(MGA1064_PIX_PLLC_M); 949fe5e51b7Smrg mgaReg->DacRegs[3] = inMGAdac(MGA1064_PIX_PLLC_N); 950fe5e51b7Smrg mgaReg->DacRegs[4] = inMGAdac(MGA1064_PIX_PLLC_P); 951fe5e51b7Smrg } 952fe5e51b7Smrg ); 953fe5e51b7Smrg#endif 954fe5e51b7Smrg MGA_NOT_HAL( 955fe5e51b7Smrg /* 956fe5e51b7Smrg * The port I/O code necessary to read in the extended registers. 957fe5e51b7Smrg */ 958fe5e51b7Smrg for (i = 0; i < DACREGSIZE; i++) 959fe5e51b7Smrg mgaReg->DacRegs[i] = inMGAdac(i); 960fe5e51b7Smrg 961fe5e51b7Smrg mgaReg->PIXPLLCSaved = TRUE; 962fe5e51b7Smrg 963fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS 964fe5e51b7Smrg pci_device_cfg_read_u32(pMga->PciInfo, & mgaReg->Option, 965fe5e51b7Smrg PCI_OPTION_REG); 966fe5e51b7Smrg pci_device_cfg_read_u32(pMga->PciInfo, & mgaReg->Option2, 967fe5e51b7Smrg PCI_MGA_OPTION2); 968fe5e51b7Smrg#else 969fe5e51b7Smrg mgaReg->Option = pciReadLong(pMga->PciTag, PCI_OPTION_REG); 970fe5e51b7Smrg 971fe5e51b7Smrg mgaReg->Option2 = pciReadLong(pMga->PciTag, PCI_MGA_OPTION2); 972fe5e51b7Smrg#endif 973fe5e51b7Smrg if (pMga->Chipset == PCI_CHIP_MGAG400 || pMga->Chipset == PCI_CHIP_MGAG550) 974fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS 975fe5e51b7Smrg pci_device_cfg_read_u32(pMga->PciInfo, & mgaReg->Option3, 976fe5e51b7Smrg PCI_MGA_OPTION3); 977fe5e51b7Smrg#else 978fe5e51b7Smrg mgaReg->Option3 = pciReadLong(pMga->PciTag, PCI_MGA_OPTION3); 979fe5e51b7Smrg#endif 980fe5e51b7Smrg ); /* MGA_NOT_HAL */ 981fe5e51b7Smrg 982fe5e51b7Smrg for (i = 0; i < 6; i++) 983fe5e51b7Smrg { 984fe5e51b7Smrg OUTREG8(MGAREG_CRTCEXT_INDEX, i); 985fe5e51b7Smrg mgaReg->ExtVga[i] = INREG8(MGAREG_CRTCEXT_DATA); 986fe5e51b7Smrg } 987fe5e51b7Smrg 988fe5e51b7Smrg#ifdef DEBUG 989fe5e51b7Smrg ErrorF("Saved values:\nDAC:"); 990fe5e51b7Smrg for (i=0; i<DACREGSIZE; i++) { 991fe5e51b7Smrg#if 1 992fe5e51b7Smrg if(!(i%16)) ErrorF("\n%02X: ",i); 993fe5e51b7Smrg ErrorF("%02X ", mgaReg->DacRegs[i]); 994fe5e51b7Smrg#else 995fe5e51b7Smrg if(!(i%8)) ErrorF("\n%02X: ",i); 996fe5e51b7Smrg ErrorF("0x%02X, ", mgaReg->DacRegs[i]); 997fe5e51b7Smrg#endif 998fe5e51b7Smrg } 999fe5e51b7Smrg ErrorF("\nOPTION = %08lX\n:", mgaReg->Option); 1000fe5e51b7Smrg ErrorF("OPTION2 = %08lX\nCRTCEXT:", mgaReg->Option2); 1001fe5e51b7Smrg for (i=0; i<6; i++) ErrorF(" %02X", mgaReg->ExtVga[i]); 1002fe5e51b7Smrg ErrorF("\n"); 1003fe5e51b7Smrg#endif 1004fe5e51b7Smrg} 1005fe5e51b7Smrg 1006fe5e51b7Smrg/**** 1007fe5e51b7Smrg *** HW Cursor 1008fe5e51b7Smrg */ 1009fe5e51b7Smrgstatic void 1010fe5e51b7SmrgMGAGLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src) 1011fe5e51b7Smrg{ 1012fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1013fe5e51b7Smrg CARD32 *dst = (CARD32*)(pMga->FbBase + pMga->FbCursorOffset); 1014fe5e51b7Smrg int i = 128; 1015fe5e51b7Smrg 1016fe5e51b7Smrg /* swap bytes in each line */ 1017fe5e51b7Smrg while( i-- ) { 1018fe5e51b7Smrg *dst++ = (src[4] << 24) | (src[5] << 16) | (src[6] << 8) | src[7]; 1019fe5e51b7Smrg *dst++ = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3]; 1020fe5e51b7Smrg src += 8; 1021fe5e51b7Smrg } 1022fe5e51b7Smrg} 1023fe5e51b7Smrg 1024fe5e51b7Smrgstatic void 1025fe5e51b7SmrgMGAGShowCursor(ScrnInfoPtr pScrn) 1026fe5e51b7Smrg{ 1027fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1028fe5e51b7Smrg /* Enable cursor - X-Windows mode */ 1029fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_CTL, 0x03); 1030fe5e51b7Smrg} 1031fe5e51b7Smrg 1032fe5e51b7Smrgstatic void 1033fe5e51b7SmrgMGAGShowCursorG100(ScrnInfoPtr pScrn) 1034fe5e51b7Smrg{ 1035fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1036fe5e51b7Smrg /* Enable cursor - X-Windows mode */ 1037fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_CTL, 0x01); 1038fe5e51b7Smrg} 1039fe5e51b7Smrg 1040fe5e51b7Smrgstatic void 1041fe5e51b7SmrgMGAGHideCursor(ScrnInfoPtr pScrn) 1042fe5e51b7Smrg{ 1043fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1044fe5e51b7Smrg /* Disable cursor */ 1045fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_CTL, 0x00); 1046fe5e51b7Smrg} 1047fe5e51b7Smrg 1048fe5e51b7Smrgstatic void 1049fe5e51b7SmrgMGAGSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) 1050fe5e51b7Smrg{ 1051fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1052fe5e51b7Smrg x += 64; 1053fe5e51b7Smrg y += 64; 1054fe5e51b7Smrg 1055fe5e51b7Smrg#ifdef USEMGAHAL 1056fe5e51b7Smrg MGA_HAL( 1057fe5e51b7Smrg x += pMga->HALGranularityOffX; 1058fe5e51b7Smrg y += pMga->HALGranularityOffY; 1059fe5e51b7Smrg ); 1060fe5e51b7Smrg#endif 1061fe5e51b7Smrg /* cursor update must never occurs during a retrace period (pp 4-160) */ 1062fe5e51b7Smrg while( INREG( MGAREG_Status ) & 0x08 ); 1063fe5e51b7Smrg 1064fe5e51b7Smrg /* Output position - "only" 12 bits of location documented */ 1065fe5e51b7Smrg OUTREG8( RAMDAC_OFFSET + MGA1064_CUR_XLOW, (x & 0xFF)); 1066fe5e51b7Smrg OUTREG8( RAMDAC_OFFSET + MGA1064_CUR_XHI, (x & 0xF00) >> 8); 1067fe5e51b7Smrg OUTREG8( RAMDAC_OFFSET + MGA1064_CUR_YLOW, (y & 0xFF)); 1068fe5e51b7Smrg OUTREG8( RAMDAC_OFFSET + MGA1064_CUR_YHI, (y & 0xF00) >> 8); 1069fe5e51b7Smrg} 1070fe5e51b7Smrg 1071fe5e51b7Smrg 1072fe5e51b7Smrgstatic void 1073fe5e51b7SmrgMGAGSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) 1074fe5e51b7Smrg{ 1075fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1076fe5e51b7Smrg 1077fe5e51b7Smrg /* Background color */ 1078fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL0_RED, (bg & 0x00FF0000) >> 16); 1079fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL0_GREEN, (bg & 0x0000FF00) >> 8); 1080fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL0_BLUE, (bg & 0x000000FF)); 1081fe5e51b7Smrg 1082fe5e51b7Smrg /* Foreground color */ 1083fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL1_RED, (fg & 0x00FF0000) >> 16); 1084fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL1_GREEN, (fg & 0x0000FF00) >> 8); 1085fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL1_BLUE, (fg & 0x000000FF)); 1086fe5e51b7Smrg} 1087fe5e51b7Smrg 1088fe5e51b7Smrgstatic void 1089fe5e51b7SmrgMGAGSetCursorColorsG100(ScrnInfoPtr pScrn, int bg, int fg) 1090fe5e51b7Smrg{ 1091fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1092fe5e51b7Smrg 1093fe5e51b7Smrg /* Background color */ 1094fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL1_RED, (bg & 0x00FF0000) >> 16); 1095fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL1_GREEN, (bg & 0x0000FF00) >> 8); 1096fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL1_BLUE, (bg & 0x000000FF)); 1097fe5e51b7Smrg 1098fe5e51b7Smrg /* Foreground color */ 1099fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL2_RED, (fg & 0x00FF0000) >> 16); 1100fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL2_GREEN, (fg & 0x0000FF00) >> 8); 1101fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL2_BLUE, (fg & 0x000000FF)); 1102fe5e51b7Smrg} 1103fe5e51b7Smrg 1104fe5e51b7Smrgstatic Bool 1105fe5e51b7SmrgMGAGUseHWCursor(ScreenPtr pScrn, CursorPtr pCurs) 1106fe5e51b7Smrg{ 1107fe5e51b7Smrg MGAPtr pMga = MGAPTR(xf86Screens[pScrn->myNum]); 1108fe5e51b7Smrg /* This needs to detect if its on the second dac */ 1109fe5e51b7Smrg if( XF86SCRNINFO(pScrn)->currentMode->Flags & V_DBLSCAN ) 1110fe5e51b7Smrg return FALSE; 1111fe5e51b7Smrg if( pMga->SecondCrtc == TRUE ) 1112fe5e51b7Smrg return FALSE; 1113fe5e51b7Smrg return TRUE; 1114fe5e51b7Smrg} 1115fe5e51b7Smrg 1116fe5e51b7Smrg 1117fe5e51b7Smrg/* 1118fe5e51b7Smrg * According to mga-1064g.pdf pp215-216 (4-179 & 4-180) the low bits of 1119fe5e51b7Smrg * XGENIODATA and XGENIOCTL are connected to the 4 DDC pins, but don't say 1120fe5e51b7Smrg * which VGA line is connected to each DDC pin, so I've had to guess. 1121fe5e51b7Smrg * 1122fe5e51b7Smrg * DDC1 support only requires DDC_SDA_MASK, 1123fe5e51b7Smrg * DDC2 support requires DDC_SDA_MASK and DDC_SCL_MASK 1124fe5e51b7Smrg * 1125fe5e51b7Smrg * If we want DDC on second head (P2) then we must use DDC2 protocol (I2C) 1126fe5e51b7Smrg * 1127fe5e51b7Smrg * Be careful, DDC1 and DDC2 refer to protocols, DDC_P1 and DDC_P2 refer to 1128fe5e51b7Smrg * DDC data coming in on which videoport on the card 1129fe5e51b7Smrg */ 1130fe5e51b7Smrgstatic const int DDC_P1_SDA_MASK = (1 << 1); 1131fe5e51b7Smrgstatic const int DDC_P1_SCL_MASK = (1 << 3); 1132fe5e51b7Smrgstatic const int DDC_P2_SDA_MASK = (1 << 0); 1133fe5e51b7Smrgstatic const int DDC_P2_SCL_MASK = (1 << 2); 1134fe5e51b7Smrgstatic const int MAVEN_SDA_MASK = (1 << 4); 1135fe5e51b7Smrgstatic const int MAVEN_SCL_MASK = (1 << 5); 1136fe5e51b7Smrg 1137fe5e51b7Smrgstatic unsigned int 1138fe5e51b7SmrgMGAG_ddc1Read(ScrnInfoPtr pScrn) 1139fe5e51b7Smrg{ 1140fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1141fe5e51b7Smrg unsigned char val; 1142fe5e51b7Smrg 1143fe5e51b7Smrg /* Define the SDA as an input */ 1144fe5e51b7Smrg outMGAdacmsk(MGA1064_GEN_IO_CTL, ~(DDC_P1_SCL_MASK | DDC_P1_SDA_MASK), 0); 1145fe5e51b7Smrg 1146fe5e51b7Smrg /* wait for Vsync */ 1147fe5e51b7Smrg if (pMga->is_G200SE) { 1148fe5e51b7Smrg usleep(4); 1149fe5e51b7Smrg } else { 1150fe5e51b7Smrg while( INREG( MGAREG_Status ) & 0x08 ); 1151fe5e51b7Smrg while( ! (INREG( MGAREG_Status ) & 0x08) ); 1152fe5e51b7Smrg } 1153fe5e51b7Smrg 1154fe5e51b7Smrg /* Get the result */ 1155fe5e51b7Smrg val = (inMGAdac(MGA1064_GEN_IO_DATA) & DDC_P1_SDA_MASK); 1156fe5e51b7Smrg return val; 1157fe5e51b7Smrg} 1158fe5e51b7Smrg 1159fe5e51b7Smrgstatic void 1160fe5e51b7SmrgMGAG_I2CGetBits(I2CBusPtr b, int *clock, int *data, int my_scl_mask, int my_sda_mask) 1161fe5e51b7Smrg{ 1162fe5e51b7Smrg ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; 1163fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1164fe5e51b7Smrg unsigned char val; 1165fe5e51b7Smrg 1166fe5e51b7Smrg /* Get the result. */ 1167fe5e51b7Smrg val = inMGAdac(MGA1064_GEN_IO_DATA); 1168fe5e51b7Smrg 1169fe5e51b7Smrg *clock = (val & my_scl_mask) != 0; 1170fe5e51b7Smrg *data = (val & my_sda_mask) != 0; 1171fe5e51b7Smrg#ifdef DEBUG 1172fe5e51b7Smrg ErrorF("MGAG_I2CGetBits(%p,...) val=0x%x, returns clock %d, data %d\n", b, val, *clock, *data); 1173fe5e51b7Smrg#endif 1174fe5e51b7Smrg} 1175fe5e51b7Smrg 1176fe5e51b7Smrg/* 1177fe5e51b7Smrg * ATTENTION! - the DATA and CLOCK lines need to be tri-stated when 1178fe5e51b7Smrg * high. Therefore turn off output driver for the line to set line 1179fe5e51b7Smrg * to high. High signal is maintained by a 15k Ohm pull-up resistor. 1180fe5e51b7Smrg */ 1181fe5e51b7Smrgstatic void 1182fe5e51b7SmrgMGAG_I2CPutBits(I2CBusPtr b, int clock, int data, int my_scl_mask, int my_sda_mask) 1183fe5e51b7Smrg{ 1184fe5e51b7Smrg ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; 1185fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1186fe5e51b7Smrg unsigned char drv, val; 1187fe5e51b7Smrg 1188fe5e51b7Smrg val = (clock ? my_scl_mask : 0) | (data ? my_sda_mask : 0); 1189fe5e51b7Smrg drv = ((!clock) ? my_scl_mask : 0) | ((!data) ? my_sda_mask : 0); 1190fe5e51b7Smrg 1191fe5e51b7Smrg /* Write the values */ 1192fe5e51b7Smrg outMGAdacmsk(MGA1064_GEN_IO_CTL, ~(my_scl_mask | my_sda_mask) , drv); 1193fe5e51b7Smrg outMGAdacmsk(MGA1064_GEN_IO_DATA, ~(my_scl_mask | my_sda_mask) , val); 1194fe5e51b7Smrg#ifdef DEBUG 1195fe5e51b7Smrg ErrorF("MGAG_I2CPutBits(%p, %d, %d) val=0x%x\n", b, clock, data, val); 1196fe5e51b7Smrg#endif 1197fe5e51b7Smrg} 1198fe5e51b7Smrg 1199fe5e51b7Smrg/* FIXME, can we use some neater way besides these silly stubs? */ 1200fe5e51b7Smrg 1201fe5e51b7Smrgstatic void 1202fe5e51b7SmrgMGAG_DDC_P1_I2CPutBits(I2CBusPtr b, int clock, int data) 1203fe5e51b7Smrg{ 1204fe5e51b7Smrg MGAG_I2CPutBits(b, clock, data, DDC_P1_SCL_MASK, DDC_P1_SDA_MASK); 1205fe5e51b7Smrg} 1206fe5e51b7Smrgstatic void 1207fe5e51b7SmrgMGAG_DDC_P2_I2CPutBits(I2CBusPtr b, int clock, int data) 1208fe5e51b7Smrg{ 1209fe5e51b7Smrg MGAG_I2CPutBits(b, clock, data, DDC_P2_SCL_MASK, DDC_P2_SDA_MASK); 1210fe5e51b7Smrg} 1211fe5e51b7Smrgstatic void 1212fe5e51b7SmrgMGAG_MAVEN_I2CPutBits(I2CBusPtr b, int clock, int data) 1213fe5e51b7Smrg{ 1214fe5e51b7Smrg MGAG_I2CPutBits(b, clock, data, MAVEN_SCL_MASK, MAVEN_SDA_MASK); 1215fe5e51b7Smrg} 1216fe5e51b7Smrg 1217fe5e51b7Smrgstatic void 1218fe5e51b7SmrgMGAG_DDC_P1_I2CGetBits(I2CBusPtr b, int *clock, int *data) 1219fe5e51b7Smrg{ 1220fe5e51b7Smrg MGAG_I2CGetBits(b, clock, data, DDC_P1_SCL_MASK, DDC_P1_SDA_MASK); 1221fe5e51b7Smrg} 1222fe5e51b7Smrgstatic void 1223fe5e51b7SmrgMGAG_DDC_P2_I2CGetBits(I2CBusPtr b, int *clock, int *data) 1224fe5e51b7Smrg{ 1225fe5e51b7Smrg MGAG_I2CGetBits(b, clock, data, DDC_P2_SCL_MASK, DDC_P2_SDA_MASK); 1226fe5e51b7Smrg} 1227fe5e51b7Smrgstatic void 1228fe5e51b7SmrgMGAG_MAVEN_I2CGetBits(I2CBusPtr b, int *clock, int *data) 1229fe5e51b7Smrg{ 1230fe5e51b7Smrg MGAG_I2CGetBits(b, clock, data, MAVEN_SCL_MASK, MAVEN_SDA_MASK); 1231fe5e51b7Smrg} 1232fe5e51b7Smrg 1233fe5e51b7SmrgBool 1234fe5e51b7SmrgMGAG_i2cInit(ScrnInfoPtr pScrn) 1235fe5e51b7Smrg{ 1236fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1237fe5e51b7Smrg I2CBusPtr I2CPtr; 1238fe5e51b7Smrg 1239fe5e51b7Smrg if (pMga->SecondCrtc == FALSE) { 1240fe5e51b7Smrg I2CPtr = xf86CreateI2CBusRec(); 1241fe5e51b7Smrg if(!I2CPtr) return FALSE; 1242fe5e51b7Smrg 1243fe5e51b7Smrg pMga->DDC_Bus1 = I2CPtr; 1244fe5e51b7Smrg 1245fe5e51b7Smrg I2CPtr->BusName = "DDC P1"; 1246fe5e51b7Smrg I2CPtr->scrnIndex = pScrn->scrnIndex; 1247fe5e51b7Smrg I2CPtr->I2CPutBits = MGAG_DDC_P1_I2CPutBits; 1248fe5e51b7Smrg I2CPtr->I2CGetBits = MGAG_DDC_P1_I2CGetBits; 1249fe5e51b7Smrg I2CPtr->AcknTimeout = 5; 1250fe5e51b7Smrg 1251fe5e51b7Smrg if (!xf86I2CBusInit(I2CPtr)) { 1252fe5e51b7Smrg xf86DestroyI2CBusRec(pMga->DDC_Bus1, TRUE, TRUE); 1253fe5e51b7Smrg pMga->DDC_Bus1 = NULL; 1254fe5e51b7Smrg return FALSE; 1255fe5e51b7Smrg } 1256fe5e51b7Smrg } 1257fe5e51b7Smrg else { 1258fe5e51b7Smrg /* We have a dual head setup on G-series, set up DDC #2. */ 1259fe5e51b7Smrg I2CPtr = xf86CreateI2CBusRec(); 1260fe5e51b7Smrg if(!I2CPtr) return FALSE; 1261fe5e51b7Smrg 1262fe5e51b7Smrg pMga->DDC_Bus2 = I2CPtr; 1263fe5e51b7Smrg 1264fe5e51b7Smrg I2CPtr->BusName = "DDC P2"; 1265fe5e51b7Smrg I2CPtr->scrnIndex = pScrn->scrnIndex; 1266fe5e51b7Smrg I2CPtr->I2CPutBits = MGAG_DDC_P2_I2CPutBits; 1267fe5e51b7Smrg I2CPtr->I2CGetBits = MGAG_DDC_P2_I2CGetBits; 1268fe5e51b7Smrg I2CPtr->AcknTimeout = 5; 1269fe5e51b7Smrg 1270fe5e51b7Smrg if (!xf86I2CBusInit(I2CPtr)) { 1271fe5e51b7Smrg xf86DestroyI2CBusRec(pMga->DDC_Bus2, TRUE, TRUE); 1272fe5e51b7Smrg pMga->DDC_Bus2 = NULL; 1273fe5e51b7Smrg } 1274fe5e51b7Smrg else { 1275fe5e51b7Smrg if (!xf86I2CProbeAddress(pMga->DDC_Bus2, 0xA0)) { /* 0xA0 is DDC EEPROM address */ 1276fe5e51b7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "DDC #2 unavailable -> TV cable connected or no monitor connected!\n"); 1277fe5e51b7Smrg pMga->Crtc2IsTV = TRUE; /* assume for now. We need to fix HAL interactions. */ 1278fe5e51b7Smrg } 1279fe5e51b7Smrg } 1280fe5e51b7Smrg 1281fe5e51b7Smrg /* Then try to set up MAVEN bus. */ 1282fe5e51b7Smrg 1283fe5e51b7Smrg I2CPtr = xf86CreateI2CBusRec(); 1284fe5e51b7Smrg if(!I2CPtr) return FALSE; 1285fe5e51b7Smrg pMga->Maven_Bus = I2CPtr; 1286fe5e51b7Smrg 1287fe5e51b7Smrg I2CPtr->BusName = "MAVEN"; 1288fe5e51b7Smrg I2CPtr->scrnIndex = pScrn->scrnIndex; 1289fe5e51b7Smrg I2CPtr->I2CPutBits = MGAG_MAVEN_I2CPutBits; 1290fe5e51b7Smrg I2CPtr->I2CGetBits = MGAG_MAVEN_I2CGetBits; 1291fe5e51b7Smrg I2CPtr->StartTimeout = 5; 1292fe5e51b7Smrg 1293fe5e51b7Smrg if (!xf86I2CBusInit(I2CPtr)) { 1294fe5e51b7Smrg xf86DestroyI2CBusRec(pMga->Maven_Bus, TRUE, TRUE); 1295fe5e51b7Smrg pMga->Maven_Bus = NULL; 1296fe5e51b7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Failed to register MAVEN I2C bus!\n"); 1297fe5e51b7Smrg } 1298fe5e51b7Smrg else { 1299fe5e51b7Smrg Bool failed = FALSE; 1300fe5e51b7Smrg /* Try to detect the MAVEN. */ 1301fe5e51b7Smrg if (xf86I2CProbeAddress(pMga->Maven_Bus, MAVEN_READ) == TRUE) { 1302fe5e51b7Smrg I2CDevPtr dp = xf86CreateI2CDevRec(); 1303fe5e51b7Smrg if (dp) { 1304fe5e51b7Smrg I2CByte maven_ver; 1305fe5e51b7Smrg 1306fe5e51b7Smrg pMga->Maven = dp; 1307fe5e51b7Smrg dp->DevName = "MGA-TVO"; 1308fe5e51b7Smrg dp->SlaveAddr = MAVEN_WRITE; 1309fe5e51b7Smrg dp->pI2CBus = pMga->Maven_Bus; 1310fe5e51b7Smrg if (!xf86I2CDevInit(dp)) { 1311fe5e51b7Smrg xf86DestroyI2CDevRec(dp, TRUE); 1312fe5e51b7Smrg pMga->Maven = NULL; 1313fe5e51b7Smrg failed = TRUE; 1314fe5e51b7Smrg } 1315fe5e51b7Smrg if (MGAMavenRead(pScrn, 0xB2, &maven_ver)) { 1316fe5e51b7Smrg if (maven_ver < 0x14) { /* heuristic stolen from matroxfb */ 1317fe5e51b7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MAVEN revision MGA-TVO-B detected (0x%x)\n", maven_ver); 1318fe5e51b7Smrg pMga->Maven_Version = 'B'; 1319fe5e51b7Smrg } 1320fe5e51b7Smrg else { 1321fe5e51b7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MAVEN revision MGA-TVO-C detected (0x%x)\n", maven_ver); 1322fe5e51b7Smrg pMga->Maven_Version = 'C'; 1323fe5e51b7Smrg } 1324fe5e51b7Smrg } 1325fe5e51b7Smrg else { 1326fe5e51b7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Failed to determine MAVEN hardware version!\n"); 1327fe5e51b7Smrg } 1328fe5e51b7Smrg } 1329fe5e51b7Smrg else { 1330fe5e51b7Smrg failed = TRUE; 1331fe5e51b7Smrg } 1332fe5e51b7Smrg } 1333fe5e51b7Smrg else { 1334fe5e51b7Smrg failed = TRUE; 1335fe5e51b7Smrg } 1336fe5e51b7Smrg 1337fe5e51b7Smrg if (failed) { 1338fe5e51b7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Failed to register MGA-TVO I2C device!\n"); 1339fe5e51b7Smrg pMga->Maven = NULL; 1340fe5e51b7Smrg pMga->Maven_Version = 0; 1341fe5e51b7Smrg } 1342fe5e51b7Smrg } 1343fe5e51b7Smrg } 1344fe5e51b7Smrg 1345fe5e51b7Smrg return TRUE; 1346fe5e51b7Smrg} 1347fe5e51b7Smrg 1348fe5e51b7Smrg 1349fe5e51b7Smrg/* 1350fe5e51b7Smrg * MGAGRamdacInit 1351fe5e51b7Smrg * Handle broken G100 special. 1352fe5e51b7Smrg */ 1353fe5e51b7Smrgstatic void 1354fe5e51b7SmrgMGAGRamdacInit(ScrnInfoPtr pScrn) 1355fe5e51b7Smrg{ 1356fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1357fe5e51b7Smrg MGARamdacPtr MGAdac = &pMga->Dac; 1358fe5e51b7Smrg 1359fe5e51b7Smrg MGAdac->isHwCursor = TRUE; 1360fe5e51b7Smrg MGAdac->CursorOffscreenMemSize = 1024; 1361fe5e51b7Smrg MGAdac->CursorMaxWidth = 64; 1362fe5e51b7Smrg MGAdac->CursorMaxHeight = 64; 1363fe5e51b7Smrg MGAdac->SetCursorPosition = MGAGSetCursorPosition; 1364fe5e51b7Smrg MGAdac->LoadCursorImage = MGAGLoadCursorImage; 1365fe5e51b7Smrg MGAdac->HideCursor = MGAGHideCursor; 1366fe5e51b7Smrg if ((pMga->Chipset == PCI_CHIP_MGAG100) 1367fe5e51b7Smrg || (pMga->Chipset == PCI_CHIP_MGAG100)) { 1368fe5e51b7Smrg MGAdac->SetCursorColors = MGAGSetCursorColorsG100; 1369fe5e51b7Smrg MGAdac->ShowCursor = MGAGShowCursorG100; 1370fe5e51b7Smrg } else { 1371fe5e51b7Smrg MGAdac->SetCursorColors = MGAGSetCursorColors; 1372fe5e51b7Smrg MGAdac->ShowCursor = MGAGShowCursor; 1373fe5e51b7Smrg } 1374fe5e51b7Smrg MGAdac->UseHWCursor = MGAGUseHWCursor; 1375fe5e51b7Smrg MGAdac->CursorFlags = 1376fe5e51b7Smrg#if X_BYTE_ORDER == X_LITTLE_ENDIAN 1377fe5e51b7Smrg HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | 1378fe5e51b7Smrg#endif 1379fe5e51b7Smrg HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 | 1380fe5e51b7Smrg HARDWARE_CURSOR_TRUECOLOR_AT_8BPP; 1381fe5e51b7Smrg 1382fe5e51b7Smrg MGAdac->LoadPalette = MGAGLoadPalette; 1383fe5e51b7Smrg MGAdac->RestorePalette = MGAGRestorePalette; 1384fe5e51b7Smrg 1385fe5e51b7Smrg 1386fe5e51b7Smrg MGAdac->maxPixelClock = pMga->bios.pixel.max_freq; 1387fe5e51b7Smrg MGAdac->ClockFrom = X_PROBED; 1388fe5e51b7Smrg 1389fe5e51b7Smrg /* Disable interleaving and set the rounding value */ 1390fe5e51b7Smrg pMga->Interleave = FALSE; 1391fe5e51b7Smrg 1392fe5e51b7Smrg pMga->Roundings[0] = 64; 1393fe5e51b7Smrg pMga->Roundings[1] = 32; 1394fe5e51b7Smrg pMga->Roundings[2] = 64; 1395fe5e51b7Smrg pMga->Roundings[3] = 32; 1396fe5e51b7Smrg 1397fe5e51b7Smrg /* Clear Fast bitblt flag */ 1398fe5e51b7Smrg pMga->HasFBitBlt = FALSE; 1399fe5e51b7Smrg} 1400fe5e51b7Smrg 1401fe5e51b7Smrgvoid MGAGSetupFuncs(ScrnInfoPtr pScrn) 1402fe5e51b7Smrg{ 1403fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1404fe5e51b7Smrg 1405fe5e51b7Smrg pMga->PreInit = MGAGRamdacInit; 1406fe5e51b7Smrg pMga->Save = MGAGSave; 1407fe5e51b7Smrg pMga->Restore = MGAGRestore; 1408fe5e51b7Smrg pMga->ModeInit = MGAGInit; 1409fe5e51b7Smrg pMga->ddc1Read = MGAG_ddc1Read; 1410fe5e51b7Smrg /* vgaHWddc1SetSpeed will only work if the card is in VGA mode */ 1411fe5e51b7Smrg pMga->DDC1SetSpeed = vgaHWddc1SetSpeedWeak(); 1412fe5e51b7Smrg pMga->i2cInit = MGAG_i2cInit; 1413fe5e51b7Smrg} 1414fe5e51b7Smrg 1415