mga_dacG.c revision 81f79626
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 that need to access the PCI config space directly need this */ 16fe5e51b7Smrg#include "xf86Pci.h" 17fe5e51b7Smrg 18fe5e51b7Smrg#include "mga_reg.h" 19fe5e51b7Smrg#include "mga.h" 20fe5e51b7Smrg#include "mga_macros.h" 21fe5e51b7Smrg#include "mga_maven.h" 22fe5e51b7Smrg 23fe5e51b7Smrg#include "xf86DDC.h" 24fe5e51b7Smrg 25fe5e51b7Smrg#include <stdlib.h> 26fe5e51b7Smrg#include <unistd.h> 27fe5e51b7Smrg 28fe5e51b7Smrg/* 29fe5e51b7Smrg * implementation 30fe5e51b7Smrg */ 31fe5e51b7Smrg 32fe5e51b7Smrg#define DACREGSIZE 0x50 33fe5e51b7Smrg 34fe5e51b7Smrg/* 35fe5e51b7Smrg * Only change bits shown in this mask. Ideally reserved bits should be 36fe5e51b7Smrg * zeroed here. Also, don't change the vgaioen bit here since it is 37fe5e51b7Smrg * controlled elsewhere. 38fe5e51b7Smrg * 39fe5e51b7Smrg * XXX These settings need to be checked. 40fe5e51b7Smrg */ 41fe5e51b7Smrg#define OPTION1_MASK 0xFFFFFEFF 42fe5e51b7Smrg#define OPTION2_MASK 0xFFFFFFFF 43fe5e51b7Smrg#define OPTION3_MASK 0xFFFFFFFF 44fe5e51b7Smrg 45fe5e51b7Smrg#define OPTION1_MASK_PRIMARY 0xFFFC0FF 46fe5e51b7Smrg 47fe5e51b7Smrgstatic void MGAGRamdacInit(ScrnInfoPtr); 48fe5e51b7Smrgstatic void MGAGSave(ScrnInfoPtr, vgaRegPtr, MGARegPtr, Bool); 49fe5e51b7Smrgstatic void MGAGRestore(ScrnInfoPtr, vgaRegPtr, MGARegPtr, Bool); 50fe5e51b7Smrgstatic Bool MGAGInit(ScrnInfoPtr, DisplayModePtr); 51fe5e51b7Smrgstatic void MGAGLoadPalette(ScrnInfoPtr, int, int*, LOCO*, VisualPtr); 52fe5e51b7Smrgstatic Bool MGAG_i2cInit(ScrnInfoPtr pScrn); 53fe5e51b7Smrg 546f68ce78Smrg#define P_ARRAY_SIZE 9 556f68ce78Smrg 566f68ce78Smrgvoid 576f68ce78SmrgMGAG200E4ComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *M, int *N, int *P) 586f68ce78Smrg{ 596f68ce78Smrg unsigned int ulComputedFo; 606f68ce78Smrg unsigned int ulFDelta; 616f68ce78Smrg unsigned int ulFTmpDelta; 626f68ce78Smrg unsigned int ulVCOMax, ulVCOMin; 636f68ce78Smrg unsigned int ulTestP; 646f68ce78Smrg unsigned int ulTestM; 656f68ce78Smrg unsigned int ulTestN; 666f68ce78Smrg unsigned int ulFoInternal; 676f68ce78Smrg unsigned int ulPLLFreqRef; 686f68ce78Smrg unsigned int pulPValues[P_ARRAY_SIZE] = {16, 14, 12, 10, 8, 6, 4, 2, 1}; 696f68ce78Smrg unsigned int i; 706f68ce78Smrg unsigned int ulVCO; 716f68ce78Smrg unsigned int ulFVV; 726f68ce78Smrg 736f68ce78Smrg ulVCOMax = 1600000; 746f68ce78Smrg ulVCOMin = 800000; 756f68ce78Smrg ulPLLFreqRef = 25000; 766f68ce78Smrg 776f68ce78Smrg if(lFo < 25000) 786f68ce78Smrg lFo = 25000; 796f68ce78Smrg 806f68ce78Smrg ulFoInternal = lFo * 2; 816f68ce78Smrg 826f68ce78Smrg ulFDelta = 0xFFFFFFFF; 836f68ce78Smrg 846f68ce78Smrg for (i = 0 ; i < P_ARRAY_SIZE ; i++) 856f68ce78Smrg { 866f68ce78Smrg ulTestP = pulPValues[i]; 876f68ce78Smrg 886f68ce78Smrg if ((ulFoInternal * ulTestP) > ulVCOMax) continue; 896f68ce78Smrg if ((ulFoInternal * ulTestP) < ulVCOMin) continue; 906f68ce78Smrg 916f68ce78Smrg for (ulTestN = 50; ulTestN <= 256; ulTestN++) { 926f68ce78Smrg for (ulTestM = 1; ulTestM <= 32; ulTestM++) { 936f68ce78Smrg ulComputedFo = (ulPLLFreqRef * ulTestN) / (ulTestM * ulTestP); 946f68ce78Smrg if (ulComputedFo > ulFoInternal) 956f68ce78Smrg ulFTmpDelta = ulComputedFo - ulFoInternal; 966f68ce78Smrg else 976f68ce78Smrg ulFTmpDelta = ulFoInternal - ulComputedFo; 986f68ce78Smrg 996f68ce78Smrg if (ulFTmpDelta < ulFDelta) { 1006f68ce78Smrg ulFDelta = ulFTmpDelta; 1016f68ce78Smrg *M = ulTestM - 1; 1026f68ce78Smrg *N = ulTestN - 1; 1036f68ce78Smrg *P = ulTestP - 1; 1046f68ce78Smrg } 1056f68ce78Smrg } 1066f68ce78Smrg } 1076f68ce78Smrg } 1086f68ce78Smrg 1096f68ce78Smrg ulVCO = ulPLLFreqRef * ((*N)+1) / ((*M)+1); 1106f68ce78Smrg ulFVV = (ulVCO - 800000) / 50000; 1116f68ce78Smrg 1126f68ce78Smrg if (ulFVV > 15) 1136f68ce78Smrg ulFVV = 15; 1146f68ce78Smrg 1156f68ce78Smrg *P |= (ulFVV << 4); 1166f68ce78Smrg 1176f68ce78Smrg *M |= 0x80; 1186f68ce78Smrg} 1196f68ce78Smrg 120fe5e51b7Smrgstatic void 121fe5e51b7SmrgMGAG200SEComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *M, int *N, int *P) 122fe5e51b7Smrg{ 123fe5e51b7Smrg unsigned int ulComputedFo; 124fe5e51b7Smrg unsigned int ulFDelta; 125fe5e51b7Smrg unsigned int ulFTmpDelta; 126fe5e51b7Smrg unsigned int ulVCOMax, ulVCOMin; 127fe5e51b7Smrg unsigned int ulTestP; 128fe5e51b7Smrg unsigned int ulTestM; 129fe5e51b7Smrg unsigned int ulTestN; 130fe5e51b7Smrg unsigned int ulPLLFreqRef; 131fe5e51b7Smrg 132fe5e51b7Smrg ulVCOMax = 320000; 133fe5e51b7Smrg ulVCOMin = 160000; 134fe5e51b7Smrg ulPLLFreqRef = 25000; 135fe5e51b7Smrg 136fe5e51b7Smrg ulFDelta = 0xFFFFFFFF; 137fe5e51b7Smrg 138fe5e51b7Smrg /* Then we need to minimize the M while staying within 0.5% */ 139fe5e51b7Smrg for (ulTestP = 8; ulTestP > 0; ulTestP >>= 1) { 140eda3803bSmrg if ((lFo * ulTestP) > ulVCOMax) continue; 141eda3803bSmrg if ((lFo * ulTestP) < ulVCOMin) continue; 142eda3803bSmrg 143eda3803bSmrg for (ulTestN = 17; ulTestN <= 256; ulTestN++) { 144eda3803bSmrg for (ulTestM = 1; ulTestM <= 32; ulTestM++) { 145eda3803bSmrg ulComputedFo = (ulPLLFreqRef * ulTestN) / (ulTestM * ulTestP); 146eda3803bSmrg if (ulComputedFo > lFo) 147eda3803bSmrg ulFTmpDelta = ulComputedFo - lFo; 148eda3803bSmrg else 149eda3803bSmrg ulFTmpDelta = lFo - ulComputedFo; 150eda3803bSmrg 151eda3803bSmrg if (ulFTmpDelta < ulFDelta) { 152eda3803bSmrg ulFDelta = ulFTmpDelta; 153eda3803bSmrg *M = ulTestM - 1; 154eda3803bSmrg *N = ulTestN - 1; 155eda3803bSmrg *P = ulTestP - 1; 156eda3803bSmrg } 157eda3803bSmrg } 158eda3803bSmrg } 159eda3803bSmrg } 160eda3803bSmrg} 161eda3803bSmrg 162eda3803bSmrgstatic void 163eda3803bSmrgMGAG200EVComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *M, int *N, int *P) 164eda3803bSmrg{ 165eda3803bSmrg unsigned int ulComputedFo; 166eda3803bSmrg unsigned int ulFDelta; 167eda3803bSmrg unsigned int ulFTmpDelta; 168eda3803bSmrg unsigned int ulTestP; 169eda3803bSmrg unsigned int ulTestM; 170eda3803bSmrg unsigned int ulTestN; 171eda3803bSmrg unsigned int ulVCOMax; 172eda3803bSmrg unsigned int ulVCOMin; 173eda3803bSmrg unsigned int ulPLLFreqRef; 174eda3803bSmrg 175eda3803bSmrg ulVCOMax = 550000; 176eda3803bSmrg ulVCOMin = 150000; 177eda3803bSmrg ulPLLFreqRef = 50000; 178eda3803bSmrg 179eda3803bSmrg ulFDelta = 0xFFFFFFFF; 180eda3803bSmrg 181eda3803bSmrg /* Then we need to minimize the M while staying within 0.5% */ 182eda3803bSmrg for (ulTestP = 16; ulTestP > 0; ulTestP--) { 183fe5e51b7Smrg if ((lFo * ulTestP) > ulVCOMax) continue; 184fe5e51b7Smrg if ((lFo * ulTestP) < ulVCOMin) continue; 185fe5e51b7Smrg 186eda3803bSmrg for (ulTestN = 1; ulTestN <= 256; ulTestN++) { 187eda3803bSmrg for (ulTestM = 1; ulTestM <= 16; ulTestM++) { 188fe5e51b7Smrg ulComputedFo = (ulPLLFreqRef * ulTestN) / (ulTestM * ulTestP); 189fe5e51b7Smrg if (ulComputedFo > lFo) 190fe5e51b7Smrg ulFTmpDelta = ulComputedFo - lFo; 191fe5e51b7Smrg else 192fe5e51b7Smrg ulFTmpDelta = lFo - ulComputedFo; 193fe5e51b7Smrg 194fe5e51b7Smrg if (ulFTmpDelta < ulFDelta) { 195eda3803bSmrg ulFDelta = ulFTmpDelta; 196eda3803bSmrg *M = (CARD8)(ulTestM - 1); 197eda3803bSmrg *N = (CARD8)(ulTestN - 1); 198eda3803bSmrg *P = (CARD8)(ulTestP - 1); 199eda3803bSmrg } 200eda3803bSmrg } 201eda3803bSmrg } 202eda3803bSmrg } 203eda3803bSmrg#if DEBUG 204eda3803bSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 205eda3803bSmrg "lFo=%ld n=0x%x m=0x%x p=0x%x \n", 206eda3803bSmrg lFo, *N, *M, *P ); 207eda3803bSmrg#endif 208eda3803bSmrg} 209eda3803bSmrg 210eda3803bSmrgstatic void 211eda3803bSmrgMGAG200WBComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *M, int *N, int *P) 212eda3803bSmrg{ 213eda3803bSmrg unsigned int ulComputedFo; 214eda3803bSmrg unsigned int ulFDelta; 215eda3803bSmrg unsigned int ulFTmpDelta; 216eda3803bSmrg unsigned int ulVCOMax, ulVCOMin; 217eda3803bSmrg unsigned int ulTestP; 218eda3803bSmrg unsigned int ulTestM; 219eda3803bSmrg unsigned int ulTestN; 220eda3803bSmrg unsigned int ulPLLFreqRef; 221eda3803bSmrg unsigned int ulTestPStart; 222eda3803bSmrg unsigned int ulTestNStart; 223eda3803bSmrg unsigned int ulTestNEnd; 224eda3803bSmrg unsigned int ulTestMStart; 225eda3803bSmrg unsigned int ulTestMEnd; 226eda3803bSmrg 227eda3803bSmrg ulVCOMax = 550000; 228eda3803bSmrg ulVCOMin = 150000; 229eda3803bSmrg ulPLLFreqRef = 48000; 230eda3803bSmrg ulTestPStart = 1; 231eda3803bSmrg ulTestNStart = 1; 232eda3803bSmrg ulTestNEnd = 150; 233eda3803bSmrg ulTestMStart = 1; 234eda3803bSmrg ulTestMEnd = 16; 235eda3803bSmrg 236eda3803bSmrg ulFDelta = 0xFFFFFFFF; 237eda3803bSmrg 238eda3803bSmrg /* Then we need to minimize the M while staying within 0.5% */ 239eda3803bSmrg for (ulTestP = ulTestPStart; ulTestP < 9; ulTestP++) { 240eda3803bSmrg if ((lFo * ulTestP) > ulVCOMax) continue; 241eda3803bSmrg if ((lFo * ulTestP) < ulVCOMin) continue; 242eda3803bSmrg 243eda3803bSmrg for (ulTestM = ulTestMStart; ulTestM <= ulTestMEnd; ulTestM++) { 244eda3803bSmrg for (ulTestN = ulTestNStart; ulTestN <= ulTestNEnd; ulTestN++) { 245eda3803bSmrg ulComputedFo = (ulPLLFreqRef * ulTestN) / (ulTestM * ulTestP); 246eda3803bSmrg if (ulComputedFo > lFo) 247eda3803bSmrg ulFTmpDelta = ulComputedFo - lFo; 248eda3803bSmrg else 249eda3803bSmrg ulFTmpDelta = lFo - ulComputedFo; 250eda3803bSmrg 251eda3803bSmrg if (ulFTmpDelta < ulFDelta) { 252eda3803bSmrg ulFDelta = ulFTmpDelta; 253eda3803bSmrg *M = (CARD8)(ulTestM - 1) | (CARD8)(((ulTestN -1) >> 1) & 0x80); 254eda3803bSmrg *N = (CARD8)(ulTestN - 1); 255eda3803bSmrg *P = (CARD8)(ulTestP - 1); 256fe5e51b7Smrg } 257fe5e51b7Smrg } 258fe5e51b7Smrg } 259fe5e51b7Smrg } 260eda3803bSmrg#if DEBUG 261eda3803bSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 262eda3803bSmrg "lFo=%ld n=0x%x m=0x%x p=0x%x \n", 263eda3803bSmrg lFo, *N, *M, *P ); 264eda3803bSmrg#endif 265fe5e51b7Smrg} 266fe5e51b7Smrg 2676f68ce78Smrgvoid 2686f68ce78SmrgMGAG200EW3ComputePLLParam(ScrnInfoPtr pScrn ,long lFo, int *M, int *N, int *P) 2696f68ce78Smrg{ 2706f68ce78Smrg unsigned int ulComputedFo; 2716f68ce78Smrg unsigned int ulFDelta; 2726f68ce78Smrg unsigned int ulFTmpDelta; 2736f68ce78Smrg unsigned int ulVCOMax, ulVCOMin; 2746f68ce78Smrg unsigned int ulTestP1; 2756f68ce78Smrg unsigned int ulTestP2; 2766f68ce78Smrg unsigned int ulTestM; 2776f68ce78Smrg unsigned int ulTestN; 2786f68ce78Smrg unsigned int ulPLLFreqRef; 2796f68ce78Smrg unsigned int ulTestP1Start; 2806f68ce78Smrg unsigned int ulTestP1End; 2816f68ce78Smrg unsigned int ulTestP2Start; 2826f68ce78Smrg unsigned int ulTestP2End; 2836f68ce78Smrg unsigned int ulTestMStart; 2846f68ce78Smrg unsigned int ulTestMEnd; 2856f68ce78Smrg unsigned int ulTestNStart; 2866f68ce78Smrg unsigned int ulTestNEnd; 2876f68ce78Smrg 2886f68ce78Smrg ulVCOMax = 800000; 2896f68ce78Smrg ulVCOMin = 400000; 2906f68ce78Smrg ulPLLFreqRef = 25000; 2916f68ce78Smrg ulTestP1Start = 1; 2926f68ce78Smrg ulTestP1End = 8; 2936f68ce78Smrg ulTestP2Start = 1; 2946f68ce78Smrg ulTestP2End = 8; 2956f68ce78Smrg ulTestMStart = 1; 2966f68ce78Smrg ulTestMEnd = 26; 2976f68ce78Smrg ulTestNStart = 32; 2986f68ce78Smrg ulTestNEnd = 2048; 2996f68ce78Smrg 3006f68ce78Smrg ulFDelta = 0xFFFFFFFF; 3016f68ce78Smrg 3026f68ce78Smrg /* Then we need to minimize the M while staying within 0.5% */ 3036f68ce78Smrg for (ulTestP1 = ulTestP1Start; ulTestP1 < ulTestP1End; ulTestP1++) { 3046f68ce78Smrg for (ulTestP2 = ulTestP2Start; ulTestP2 < ulTestP2End; ulTestP2++) { 3056f68ce78Smrg if (ulTestP1 < ulTestP2) continue; 3066f68ce78Smrg if ((lFo * ulTestP1 * ulTestP2) > ulVCOMax) continue; 3076f68ce78Smrg if ((lFo * ulTestP1 * ulTestP2) < ulVCOMin) continue; 3086f68ce78Smrg 3096f68ce78Smrg for (ulTestM = ulTestMStart; ulTestM < ulTestMEnd; ulTestM++) { 3106f68ce78Smrg for (ulTestN = ulTestNStart; ulTestN < ulTestNEnd; ulTestN++) { 3116f68ce78Smrg ulComputedFo = (ulPLLFreqRef * ulTestN) / (ulTestM * ulTestP1 * ulTestP2); 3126f68ce78Smrg if (ulComputedFo > lFo) 3136f68ce78Smrg ulFTmpDelta = ulComputedFo - lFo; 3146f68ce78Smrg else 3156f68ce78Smrg ulFTmpDelta = lFo - ulComputedFo; 3166f68ce78Smrg 3176f68ce78Smrg if (ulFTmpDelta < ulFDelta) { 3186f68ce78Smrg ulFDelta = ulFTmpDelta; 3196f68ce78Smrg *M = (CARD8)((ulTestN & 0x100) >> 1) | 3206f68ce78Smrg (CARD8)(ulTestM); 3216f68ce78Smrg *N = (CARD8)(ulTestN & 0xFF); 3226f68ce78Smrg *P = (CARD8)((ulTestN & 0x600) >> 3) | 3236f68ce78Smrg (CARD8)(ulTestP2 << 3) | 3246f68ce78Smrg (CARD8)ulTestP1; 3256f68ce78Smrg } 3266f68ce78Smrg } 3276f68ce78Smrg } 3286f68ce78Smrg } 3296f68ce78Smrg } 3306f68ce78Smrg} 3316f68ce78Smrg 332a31a186aSmrgstatic void 333a31a186aSmrgMGAG200EHComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *M, int *N, int *P) 334a31a186aSmrg{ 335a31a186aSmrg unsigned int ulComputedFo; 336a31a186aSmrg unsigned int ulFDelta; 337a31a186aSmrg unsigned int ulFTmpDelta; 338a31a186aSmrg unsigned int ulTestP; 339a31a186aSmrg unsigned int ulTestM; 340a31a186aSmrg unsigned int ulTestN; 341a31a186aSmrg unsigned int ulVCOMax; 342a31a186aSmrg unsigned int ulVCOMin; 343a31a186aSmrg unsigned int ulPLLFreqRef; 344a31a186aSmrg 345a31a186aSmrg ulVCOMax = 800000; 346a31a186aSmrg ulVCOMin = 400000; 347a31a186aSmrg ulPLLFreqRef = 33333; 348a31a186aSmrg 349a31a186aSmrg ulFDelta = 0xFFFFFFFF; 350a31a186aSmrg 351a31a186aSmrg /* Then we need to minimize the M while staying within 0.5% */ 352a31a186aSmrg for (ulTestP = 16; ulTestP > 0; ulTestP>>= 1) { 353a31a186aSmrg if ((lFo * ulTestP) > ulVCOMax) continue; 354a31a186aSmrg if ((lFo * ulTestP) < ulVCOMin) continue; 355a31a186aSmrg 356a31a186aSmrg for (ulTestM = 1; ulTestM <= 32; ulTestM++) { 357a31a186aSmrg for (ulTestN = 17; ulTestN <= 256; ulTestN++) { 358a31a186aSmrg ulComputedFo = (ulPLLFreqRef * ulTestN) / (ulTestM * ulTestP); 359a31a186aSmrg if (ulComputedFo > lFo) 360a31a186aSmrg ulFTmpDelta = ulComputedFo - lFo; 361a31a186aSmrg else 362a31a186aSmrg ulFTmpDelta = lFo - ulComputedFo; 363a31a186aSmrg 364a31a186aSmrg if (ulFTmpDelta < ulFDelta) { 365a31a186aSmrg ulFDelta = ulFTmpDelta; 366a31a186aSmrg *M = (CARD8)(ulTestM - 1); 367a31a186aSmrg *N = (CARD8)(ulTestN - 1); 368a31a186aSmrg *P = (CARD8)(ulTestP - 1); 369a31a186aSmrg } 370a31a186aSmrg 371a31a186aSmrg if ((lFo * ulTestP) >= 600000) 372a31a186aSmrg *P |= 0x80; 373a31a186aSmrg } 374a31a186aSmrg } 375a31a186aSmrg } 376a31a186aSmrg} 377a31a186aSmrg 37881f79626Smrgvoid 37981f79626SmrgMGAG200EH3ComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *M, int *N, int *P) 38081f79626Smrg{ 38181f79626Smrg unsigned int ulComputedFo; 38281f79626Smrg unsigned int ulFDelta; 38381f79626Smrg unsigned int ulFTmpDelta; 38481f79626Smrg unsigned int ulTestP; 38581f79626Smrg unsigned int ulTestM; 38681f79626Smrg unsigned int ulTestN; 38781f79626Smrg unsigned int ulVCOMax; 38881f79626Smrg unsigned int ulVCOMin; 38981f79626Smrg unsigned int ulPLLFreqRef; 39081f79626Smrg 39181f79626Smrg ulVCOMax = 3000000; 39281f79626Smrg ulVCOMin = 1500000; 39381f79626Smrg ulPLLFreqRef = 25000; 39481f79626Smrg 39581f79626Smrg ulTestP = 0; 39681f79626Smrg 39781f79626Smrg ulFDelta = 0xFFFFFFFF; 39881f79626Smrg 39981f79626Smrg /* Then we need to minimize the M while staying within 0.5% */ 40081f79626Smrg for (ulTestM = 150; ulTestM >= 6; ulTestM--) { 40181f79626Smrg if ((lFo * ulTestM) > ulVCOMax) continue; 40281f79626Smrg if ((lFo * ulTestM) < ulVCOMin) continue; 40381f79626Smrg 40481f79626Smrg for (ulTestN = 120; ulTestN >= 60; ulTestN--) { 40581f79626Smrg ulComputedFo = (ulPLLFreqRef * ulTestN) / ulTestM; 40681f79626Smrg if (ulComputedFo > lFo) 40781f79626Smrg ulFTmpDelta = ulComputedFo - lFo; 40881f79626Smrg else 40981f79626Smrg ulFTmpDelta = lFo - ulComputedFo; 41081f79626Smrg 41181f79626Smrg if (ulFTmpDelta < ulFDelta) { 41281f79626Smrg ulFDelta = ulFTmpDelta; 41381f79626Smrg *M = (CARD8)(ulTestM); 41481f79626Smrg *N = (CARD8)(ulTestN); 41581f79626Smrg *P = (CARD8)(ulTestP); 41681f79626Smrg } 41781f79626Smrg } 41881f79626Smrg } 41981f79626Smrg} 42081f79626Smrg 421eda3803bSmrgstatic void 422eda3803bSmrgMGAG200EVPIXPLLSET(ScrnInfoPtr pScrn, MGARegPtr mgaReg) 423eda3803bSmrg{ 424eda3803bSmrg MGAPtr pMga = MGAPTR(pScrn); 425eda3803bSmrg 426eda3803bSmrg unsigned char ucTempByte, ucPixCtrl; 427eda3803bSmrg 428eda3803bSmrg // Set pixclkdis to 1 429eda3803bSmrg ucPixCtrl = inMGAdac(MGA1064_PIX_CLK_CTL); 430eda3803bSmrg ucPixCtrl |= MGA1064_PIX_CLK_CTL_CLK_DIS; 431eda3803bSmrg outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl); 432eda3803bSmrg 433eda3803bSmrg // Select PLL Set C 434eda3803bSmrg ucTempByte = INREG8(MGAREG_MEM_MISC_READ); 435eda3803bSmrg ucTempByte |= 0x3<<2; //select MGA pixel clock 436eda3803bSmrg OUTREG8(MGAREG_MEM_MISC_WRITE, ucTempByte); 437eda3803bSmrg 438eda3803bSmrg // Set pixlock to 0 439eda3803bSmrg ucTempByte = inMGAdac(MGA1064_PIX_PLL_STAT); 440eda3803bSmrg outMGAdac(MGA1064_PIX_PLL_STAT, ucTempByte & ~0x40); 441eda3803bSmrg 442eda3803bSmrg // Set pix_stby to 1 443eda3803bSmrg ucPixCtrl |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; 444eda3803bSmrg outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl); 445eda3803bSmrg 446eda3803bSmrg // Program the Pixel PLL Register 447eda3803bSmrg outMGAdac(MGA1064_EV_PIX_PLLC_M, mgaReg->PllM); 448eda3803bSmrg outMGAdac(MGA1064_EV_PIX_PLLC_N, mgaReg->PllN); 449eda3803bSmrg outMGAdac(MGA1064_EV_PIX_PLLC_P, mgaReg->PllP); 450eda3803bSmrg 451eda3803bSmrg // Wait 50 us 452eda3803bSmrg usleep(50); 453eda3803bSmrg 454eda3803bSmrg // Set pix_stby to 0 455eda3803bSmrg ucPixCtrl &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; 456eda3803bSmrg outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl); 457eda3803bSmrg 458eda3803bSmrg // Wait 500 us 459eda3803bSmrg usleep(500); 460eda3803bSmrg 461eda3803bSmrg // Select the pixel PLL by setting pixclksel to 1 462eda3803bSmrg ucTempByte = inMGAdac(MGA1064_PIX_CLK_CTL); 463eda3803bSmrg ucTempByte &= ~MGA1064_PIX_CLK_CTL_SEL_MSK; 464eda3803bSmrg ucTempByte |= MGA1064_PIX_CLK_CTL_SEL_PLL; 465eda3803bSmrg outMGAdac(MGA1064_PIX_CLK_CTL, ucTempByte); 466eda3803bSmrg 467eda3803bSmrg // Set pixlock to 1 468eda3803bSmrg ucTempByte = inMGAdac(MGA1064_PIX_PLL_STAT); 469eda3803bSmrg outMGAdac(MGA1064_PIX_CLK_CTL, ucTempByte | 0x40); 470eda3803bSmrg 471eda3803bSmrg // Reset dotclock rate bit. 472eda3803bSmrg ucTempByte = INREG8(MGAREG_MEM_MISC_READ); 473eda3803bSmrg ucTempByte |= 0x3<<2; //select MGA pixel clock 474eda3803bSmrg OUTREG8(MGAREG_MEM_MISC_WRITE, ucTempByte); 475eda3803bSmrg 476eda3803bSmrg OUTREG8(MGAREG_SEQ_INDEX, 1); 477eda3803bSmrg ucTempByte = INREG8(MGAREG_SEQ_DATA); 478eda3803bSmrg OUTREG8(MGAREG_SEQ_DATA, ucTempByte & ~0x8); 479eda3803bSmrg 480eda3803bSmrg // Set pixclkdis to 0 481eda3803bSmrg ucTempByte = inMGAdac(MGA1064_PIX_CLK_CTL); 482eda3803bSmrg ucTempByte &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; 483eda3803bSmrg outMGAdac(MGA1064_PIX_CLK_CTL, ucTempByte); 484eda3803bSmrg} 485eda3803bSmrg 486eda3803bSmrgstatic void 487eda3803bSmrgMGAG200WBPIXPLLSET(ScrnInfoPtr pScrn, MGARegPtr mgaReg) 488eda3803bSmrg{ 489eda3803bSmrg MGAPtr pMga = MGAPTR(pScrn); 490eda3803bSmrg 491eda3803bSmrg unsigned long ulLoopCount, ulLockCheckIterations = 0, ulTempCount, ulVCount; 492eda3803bSmrg unsigned char ucTempByte, ucPixCtrl, ucPLLLocked = FALSE; 493eda3803bSmrg 494eda3803bSmrg while(ulLockCheckIterations <= 32 && ucPLLLocked == FALSE) 495eda3803bSmrg { 496eda3803bSmrg if(ulLockCheckIterations > 0) 497eda3803bSmrg { 498eda3803bSmrg OUTREG8(MGAREG_CRTCEXT_INDEX, 0x1E); 499eda3803bSmrg ucTempByte = INREG8(MGAREG_CRTCEXT_DATA); 500eda3803bSmrg if(ucTempByte < 0xFF) 501eda3803bSmrg { 502eda3803bSmrg OUTREG8(MGAREG_CRTCEXT_DATA, ucTempByte+1); 503eda3803bSmrg } 504eda3803bSmrg } 505eda3803bSmrg 506eda3803bSmrg // Set pixclkdis to 1 507eda3803bSmrg ucPixCtrl = inMGAdac(MGA1064_PIX_CLK_CTL); 508eda3803bSmrg ucPixCtrl |= MGA1064_PIX_CLK_CTL_CLK_DIS; 509eda3803bSmrg outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl); 510eda3803bSmrg 511eda3803bSmrg ucTempByte = inMGAdac(MGA1064_REMHEADCTL); 512eda3803bSmrg ucTempByte |= MGA1064_REMHEADCTL_CLKDIS; 513eda3803bSmrg outMGAdac(MGA1064_REMHEADCTL, ucTempByte); 514eda3803bSmrg 515eda3803bSmrg // Select PLL Set C 516eda3803bSmrg ucTempByte = INREG8(MGAREG_MEM_MISC_READ); 517eda3803bSmrg ucTempByte |= 0x3<<2; //select MGA pixel clock 518eda3803bSmrg OUTREG8(MGAREG_MEM_MISC_WRITE, ucTempByte); 519eda3803bSmrg 520eda3803bSmrg ucPixCtrl |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN | 0x80; 521eda3803bSmrg outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl); 522eda3803bSmrg 523eda3803bSmrg // Wait 500 us 524eda3803bSmrg usleep(500); 525eda3803bSmrg 526eda3803bSmrg // Reset the PLL 527eda3803bSmrg // When we are varying the output frequency by more than 528eda3803bSmrg // 10%, we must reset the PLL. However to be prudent, we 529eda3803bSmrg // will reset it each time that we are changing it. 530eda3803bSmrg ucTempByte = inMGAdac(MGA1064_VREF_CTL); 531eda3803bSmrg ucTempByte &= ~0x04; 532eda3803bSmrg outMGAdac(MGA1064_VREF_CTL, ucTempByte ); 533eda3803bSmrg 534eda3803bSmrg // Wait 50 us 535eda3803bSmrg usleep(50); 536eda3803bSmrg 537eda3803bSmrg // Program the Pixel PLL Register 538eda3803bSmrg outMGAdac(MGA1064_WB_PIX_PLLC_N, mgaReg->PllN); 539a31a186aSmrg outMGAdac(MGA1064_WB_PIX_PLLC_M, mgaReg->PllM); 540eda3803bSmrg outMGAdac(MGA1064_WB_PIX_PLLC_P, mgaReg->PllP); 541eda3803bSmrg 542eda3803bSmrg // Wait 50 us 543eda3803bSmrg usleep(50); 544eda3803bSmrg 545eda3803bSmrg // Turning the PLL on 546eda3803bSmrg ucTempByte = inMGAdac(MGA1064_VREF_CTL); 547eda3803bSmrg ucTempByte |= 0x04; 548eda3803bSmrg outMGAdac(MGA1064_VREF_CTL, ucTempByte ); 549eda3803bSmrg 550eda3803bSmrg // Wait 500 us 551eda3803bSmrg usleep(500); 552eda3803bSmrg 553eda3803bSmrg // Select the pixel PLL by setting pixclksel to 1 554eda3803bSmrg ucTempByte = inMGAdac(MGA1064_PIX_CLK_CTL); 555eda3803bSmrg ucTempByte &= ~MGA1064_PIX_CLK_CTL_SEL_MSK; 556eda3803bSmrg ucTempByte |= MGA1064_PIX_CLK_CTL_SEL_PLL; 557eda3803bSmrg outMGAdac(MGA1064_PIX_CLK_CTL, ucTempByte); 558eda3803bSmrg 559eda3803bSmrg ucTempByte = inMGAdac(MGA1064_REMHEADCTL); 560eda3803bSmrg ucTempByte &= ~MGA1064_REMHEADCTL_CLKSL_MSK; 561eda3803bSmrg ucTempByte |= MGA1064_REMHEADCTL_CLKSL_PLL; 562eda3803bSmrg outMGAdac(MGA1064_REMHEADCTL, ucTempByte); 563eda3803bSmrg 564eda3803bSmrg // Reset dotclock rate bit. 565eda3803bSmrg OUTREG8(MGAREG_SEQ_INDEX, 1); 566eda3803bSmrg ucTempByte = INREG8(MGAREG_SEQ_DATA); 567eda3803bSmrg OUTREG8(MGAREG_SEQ_DATA, ucTempByte & ~0x8); 568eda3803bSmrg 569eda3803bSmrg // Set pixclkdis to 0 570eda3803bSmrg ucTempByte = inMGAdac(MGA1064_PIX_CLK_CTL); 571eda3803bSmrg ucTempByte &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; 572eda3803bSmrg outMGAdac(MGA1064_PIX_CLK_CTL, ucTempByte); 573eda3803bSmrg 574eda3803bSmrg // Poll VCount. If it increments twice inside 150us, 575eda3803bSmrg // we assume that the PLL has locked. 576eda3803bSmrg ulLoopCount = 0; 577eda3803bSmrg ulVCount = INREG(MGAREG_VCOUNT); 578eda3803bSmrg 579eda3803bSmrg while(ulLoopCount < 30 && ucPLLLocked == FALSE) 580eda3803bSmrg { 581eda3803bSmrg ulTempCount = INREG(MGAREG_VCOUNT); 582eda3803bSmrg 583eda3803bSmrg if(ulTempCount < ulVCount) 584eda3803bSmrg { 585eda3803bSmrg ulVCount = 0; 586eda3803bSmrg } 587eda3803bSmrg if ((ucTempByte - ulVCount) > 2) 588eda3803bSmrg { 589eda3803bSmrg ucPLLLocked = TRUE; 590eda3803bSmrg } 591eda3803bSmrg else 592eda3803bSmrg { 593eda3803bSmrg usleep(5); 594eda3803bSmrg } 595eda3803bSmrg ulLoopCount++; 596eda3803bSmrg } 597eda3803bSmrg ulLockCheckIterations++; 598eda3803bSmrg } 599eda3803bSmrg 600eda3803bSmrg // Set remclkdis to 0 601eda3803bSmrg ucTempByte = inMGAdac(MGA1064_REMHEADCTL); 602eda3803bSmrg ucTempByte &= ~MGA1064_REMHEADCTL_CLKDIS; 603eda3803bSmrg outMGAdac(MGA1064_REMHEADCTL, ucTempByte); 604eda3803bSmrg} 605eda3803bSmrg 6060bb88ba4Smrg#define G200ER_PLLREF 48000 6070bb88ba4Smrg#define G200ER_VCOMIN 1056000 6080bb88ba4Smrg#define G200ER_VCOMAX 1488000 6090bb88ba4Smrg 6100bb88ba4Smrgstatic void MGAG200ERComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *piM, int *piN, int *piP) 6110bb88ba4Smrg{ 6120bb88ba4Smrg 6130bb88ba4Smrg int ulM; 6140bb88ba4Smrg int ulN; 6150bb88ba4Smrg int ulO; 6160bb88ba4Smrg int ulR; 6170bb88ba4Smrg 6180bb88ba4Smrg CARD32 ulComputedFo; 6190bb88ba4Smrg CARD32 ulVco; 6200bb88ba4Smrg CARD32 ulFDelta; 6210bb88ba4Smrg CARD32 ulFTmpDelta; 6220bb88ba4Smrg 6230bb88ba4Smrg CARD32 aulMDivValue[] = {1, 2, 4, 8}; 6240bb88ba4Smrg 6250bb88ba4Smrg CARD32 ulFo = lFo; 6260bb88ba4Smrg 6270bb88ba4Smrg ulFDelta = 0xFFFFFFFF; 6280bb88ba4Smrg 6290bb88ba4Smrg for (ulR = 0; ulR < 4; ulR++) 6300bb88ba4Smrg { 6310bb88ba4Smrg if(ulFDelta==0) break; 6320bb88ba4Smrg for (ulN = 5; (ulN <= 128) ; ulN++) 6330bb88ba4Smrg { 6340bb88ba4Smrg if(ulFDelta==0) break; 6350bb88ba4Smrg for (ulM = 3; ulM >= 0; ulM--) 6360bb88ba4Smrg { 6370bb88ba4Smrg if(ulFDelta==0) break; 6380bb88ba4Smrg for (ulO = 5; ulO <= 32; ulO++) 6390bb88ba4Smrg { 6400bb88ba4Smrg ulVco = (G200ER_PLLREF * (ulN+1)) / (ulR+1); 6410bb88ba4Smrg // Validate vco 6420bb88ba4Smrg if (ulVco < G200ER_VCOMIN) continue; 6430bb88ba4Smrg if (ulVco > G200ER_VCOMAX) continue; 6440bb88ba4Smrg ulComputedFo = ulVco / (aulMDivValue[ulM] * (ulO+1)); 6450bb88ba4Smrg 6460bb88ba4Smrg if (ulComputedFo > ulFo) 6470bb88ba4Smrg { 6480bb88ba4Smrg ulFTmpDelta = ulComputedFo - ulFo; 6490bb88ba4Smrg } 6500bb88ba4Smrg else 6510bb88ba4Smrg { 6520bb88ba4Smrg ulFTmpDelta = ulFo - ulComputedFo; 6530bb88ba4Smrg } 6540bb88ba4Smrg 6550bb88ba4Smrg if (ulFTmpDelta < ulFDelta) 6560bb88ba4Smrg { 6570bb88ba4Smrg ulFDelta = ulFTmpDelta; 6580bb88ba4Smrg // XG200ERPIXPLLCM M<1:0> O<7:3> 6590bb88ba4Smrg *piM = (CARD8)ulM | (CARD8)(ulO<<3); 6600bb88ba4Smrg // 6610bb88ba4Smrg // XG200ERPIXPLLCN N<6:0> 6620bb88ba4Smrg *piN = (CARD8)ulN; 6630bb88ba4Smrg // 6640bb88ba4Smrg // XG200ERPIXPLLCP R<1:0> cg<7:4> (Use R value) 6650bb88ba4Smrg *piP = (CARD8)ulR | (CARD8)(ulR<<3); 6660bb88ba4Smrg 6670bb88ba4Smrg // Test 6680bb88ba4Smrg int ftest = (G200ER_PLLREF * (ulN+1)) / ((ulR+1) * aulMDivValue[ulM] * (ulO+1)); 6690bb88ba4Smrg ftest=ftest; 6700bb88ba4Smrg } 6710bb88ba4Smrg } // End O Loop 6720bb88ba4Smrg } // End M Loop 6730bb88ba4Smrg } // End N Loop 6740bb88ba4Smrg } // End R Loop 6750bb88ba4Smrg} 6760bb88ba4Smrg 6770bb88ba4Smrgstatic void 6780bb88ba4SmrgMGAG200ERPIXPLLSET(ScrnInfoPtr pScrn, MGARegPtr mgaReg) 6790bb88ba4Smrg{ 6800bb88ba4Smrg //TODO G200ER Validate sequence 6810bb88ba4Smrg CARD8 ucPixCtrl, ucTempByte; 6820bb88ba4Smrg MGAPtr pMga = MGAPTR(pScrn); 6830bb88ba4Smrg 6840bb88ba4Smrg 6850bb88ba4Smrg // Set pixclkdis to 1 6860bb88ba4Smrg ucPixCtrl = inMGAdac(MGA1064_PIX_CLK_CTL); 6870bb88ba4Smrg ucPixCtrl |= MGA1064_PIX_CLK_CTL_CLK_DIS; 6880bb88ba4Smrg outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl); 6890bb88ba4Smrg 6900bb88ba4Smrg ucTempByte = inMGAdac(MGA1064_REMHEADCTL); 6910bb88ba4Smrg ucTempByte |= MGA1064_REMHEADCTL_CLKDIS; 6920bb88ba4Smrg outMGAdac(MGA1064_REMHEADCTL, ucTempByte); 6930bb88ba4Smrg 6940bb88ba4Smrg // Select PLL Set C 6950bb88ba4Smrg ucTempByte = INREG8(MGAREG_MEM_MISC_READ); 6960bb88ba4Smrg ucTempByte |= (0x3<<2) | 0xc0; //select MGA pixel clock 6970bb88ba4Smrg OUTREG8(MGAREG_MEM_MISC_WRITE, ucTempByte); 6980bb88ba4Smrg 6990bb88ba4Smrg ucPixCtrl &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; 7000bb88ba4Smrg ucPixCtrl |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; 7010bb88ba4Smrg outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl); 7020bb88ba4Smrg 7030bb88ba4Smrg // Wait 500 us 7040bb88ba4Smrg usleep(500); 7050bb88ba4Smrg 7060bb88ba4Smrg // Program the Pixel PLL Register 7070bb88ba4Smrg outMGAdac(MGA1064_ER_PIX_PLLC_N, mgaReg->PllN); 7080bb88ba4Smrg outMGAdac(MGA1064_ER_PIX_PLLC_M, mgaReg->PllM); 7090bb88ba4Smrg outMGAdac(MGA1064_ER_PIX_PLLC_P, mgaReg->PllP); 7100bb88ba4Smrg 7110bb88ba4Smrg // Wait 50 us 7120bb88ba4Smrg usleep(50); 7130bb88ba4Smrg 7140bb88ba4Smrg} 7150bb88ba4Smrg 716eda3803bSmrgstatic void 717eda3803bSmrgMGAG200WBPrepareForModeSwitch(ScrnInfoPtr pScrn) 718eda3803bSmrg{ 719eda3803bSmrg MGAPtr pMga = MGAPTR(pScrn); 720eda3803bSmrg 721eda3803bSmrg unsigned char ucTmpData = 0; 722eda3803bSmrg int ulIterationMax = 0; 723eda3803bSmrg // 1- The first step is to warn the BMC of an upcoming mode change. 724eda3803bSmrg // We are putting the misc<0> to output. 725eda3803bSmrg ucTmpData = inMGAdac(MGA1064_GEN_IO_CTL); 726eda3803bSmrg ucTmpData |= 0x10; 727eda3803bSmrg outMGAdac(MGA1064_GEN_IO_CTL, ucTmpData); 728eda3803bSmrg 729eda3803bSmrg // We are putting a 1 on the misc<0> line. 730eda3803bSmrg ucTmpData = inMGAdac(MGA1064_GEN_IO_DATA); 731eda3803bSmrg ucTmpData |= 0x10; 732eda3803bSmrg outMGAdac(MGA1064_GEN_IO_DATA, ucTmpData); 733eda3803bSmrg 734eda3803bSmrg // 2- The second step is to mask any further scan request 735eda3803bSmrg // This will be done by asserting the remfreqmsk bit (XSPAREREG<7>) 736eda3803bSmrg ucTmpData = inMGAdac(MGA1064_SPAREREG); 737eda3803bSmrg ucTmpData |= 0x80; 738eda3803bSmrg outMGAdac(MGA1064_SPAREREG, ucTmpData); 739eda3803bSmrg 740eda3803bSmrg // 3a- The third step is to verify if there is an active scan 741eda3803bSmrg // We are searching for a 0 on remhsyncsts (XSPAREREG<0>) 742eda3803bSmrg ulIterationMax = 300; 743eda3803bSmrg while (!(ucTmpData & 0x01) && ulIterationMax) 744eda3803bSmrg { 745eda3803bSmrg ucTmpData = inMGAdac(MGA1064_SPAREREG); 746eda3803bSmrg usleep(1000); 747eda3803bSmrg ulIterationMax--; 748eda3803bSmrg } 749eda3803bSmrg 750eda3803bSmrg // 3b- This step occurs only if the remote is actually scanning 751eda3803bSmrg // We are waiting for the end of the frame which is a 1 on 752eda3803bSmrg // remvsyncsts (XSPAREREG<1>) 753eda3803bSmrg if (ulIterationMax) 754eda3803bSmrg { 755eda3803bSmrg ulIterationMax = 300; 756eda3803bSmrg while ((ucTmpData & 0x02) && ulIterationMax) 757eda3803bSmrg { 758eda3803bSmrg ucTmpData = inMGAdac(MGA1064_SPAREREG); 759eda3803bSmrg usleep(1000); 760eda3803bSmrg ulIterationMax--; 761eda3803bSmrg } 762eda3803bSmrg } 763eda3803bSmrg} 764eda3803bSmrg 765eda3803bSmrgstatic void 766eda3803bSmrgMGAG200WBRestoreFromModeSwitch(ScrnInfoPtr pScrn) 767eda3803bSmrg{ 768eda3803bSmrg MGAPtr pMga = MGAPTR(pScrn); 769eda3803bSmrg 770eda3803bSmrg unsigned char ucTmpData = 0; 771eda3803bSmrg 772eda3803bSmrg // 1- The first step is to ensure that the vrsten and hrsten are set 773eda3803bSmrg OUTREG8(MGAREG_CRTCEXT_INDEX, 0x01); 774eda3803bSmrg ucTmpData = INREG8(MGAREG_CRTCEXT_DATA); 775eda3803bSmrg OUTREG8(MGAREG_CRTCEXT_DATA, ucTmpData | 0x88); 776eda3803bSmrg 777eda3803bSmrg // 2- The second step is is to assert the rstlvl2 778eda3803bSmrg ucTmpData = inMGAdac(MGA1064_REMHEADCTL2); 779eda3803bSmrg ucTmpData |= 0x08; 780eda3803bSmrg outMGAdac(MGA1064_REMHEADCTL2, ucTmpData); 781eda3803bSmrg 782eda3803bSmrg // - Wait for 10 us 783eda3803bSmrg usleep(10); 784eda3803bSmrg 785eda3803bSmrg // 3- The next step is is to deassert the rstlvl2 786eda3803bSmrg ucTmpData &= ~0x08; 787eda3803bSmrg outMGAdac(MGA1064_REMHEADCTL2, ucTmpData); 788eda3803bSmrg 789eda3803bSmrg // - Wait for 10 us 790eda3803bSmrg usleep(10); 791eda3803bSmrg 792eda3803bSmrg // 4- The fourth step is to remove the mask of scan request 793eda3803bSmrg // This will be done by deasserting the remfreqmsk bit (XSPAREREG<7>) 794eda3803bSmrg ucTmpData = inMGAdac(MGA1064_SPAREREG); 795eda3803bSmrg ucTmpData &= ~0x80; 796eda3803bSmrg outMGAdac(MGA1064_SPAREREG, ucTmpData); 797eda3803bSmrg 798eda3803bSmrg // 5- Finally, we are putting back a 0 on the misc<0> line. 799eda3803bSmrg ucTmpData = inMGAdac(MGA1064_GEN_IO_DATA); 800eda3803bSmrg ucTmpData &= ~0x10; 801eda3803bSmrg outMGAdac(MGA1064_GEN_IO_DATA, ucTmpData); 802eda3803bSmrg} 803fe5e51b7Smrg 804a31a186aSmrgstatic void 805a31a186aSmrgMGAG200EHPIXPLLSET(ScrnInfoPtr pScrn, MGARegPtr mgaReg) 806a31a186aSmrg{ 807a31a186aSmrg MGAPtr pMga = MGAPTR(pScrn); 808a31a186aSmrg 80981f79626Smrg unsigned long ulLoopCount, ulLockCheckIterations = 0, ulTempCount, ulVCount; 810a31a186aSmrg unsigned char ucTempByte, ucPixCtrl, ucPLLLocked = FALSE; 811a31a186aSmrg 812a31a186aSmrg while(ulLockCheckIterations <= 32 && ucPLLLocked == FALSE) 813a31a186aSmrg { 814a31a186aSmrg // Set pixclkdis to 1 815a31a186aSmrg ucPixCtrl = inMGAdac(MGA1064_PIX_CLK_CTL); 816a31a186aSmrg ucPixCtrl |= MGA1064_PIX_CLK_CTL_CLK_DIS; 817a31a186aSmrg outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl); 818a31a186aSmrg 819a31a186aSmrg // Select PLL Set C 820a31a186aSmrg ucTempByte = INREG8(MGAREG_MEM_MISC_READ); 821a31a186aSmrg ucTempByte |= 0x3<<2; //select MGA pixel clock 822a31a186aSmrg OUTREG8(MGAREG_MEM_MISC_WRITE, ucTempByte); 823a31a186aSmrg 824a31a186aSmrg ucPixCtrl |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; 825a31a186aSmrg ucPixCtrl &= ~0x80; 826a31a186aSmrg outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl); 827a31a186aSmrg 828a31a186aSmrg // Wait 500 us 829a31a186aSmrg usleep(500); 830a31a186aSmrg 831a31a186aSmrg // Program the Pixel PLL Register 832a31a186aSmrg outMGAdac(MGA1064_EH_PIX_PLLC_N, mgaReg->PllN); 833a31a186aSmrg outMGAdac(MGA1064_EH_PIX_PLLC_M, mgaReg->PllM); 834a31a186aSmrg outMGAdac(MGA1064_EH_PIX_PLLC_P, mgaReg->PllP); 835a31a186aSmrg 836a31a186aSmrg // Wait 500 us 837a31a186aSmrg usleep(500); 838a31a186aSmrg 839a31a186aSmrg // Select the pixel PLL by setting pixclksel to 1 840a31a186aSmrg ucTempByte = inMGAdac(MGA1064_PIX_CLK_CTL); 841a31a186aSmrg ucTempByte &= ~MGA1064_PIX_CLK_CTL_SEL_MSK; 842a31a186aSmrg ucTempByte |= MGA1064_PIX_CLK_CTL_SEL_PLL; 843a31a186aSmrg outMGAdac(MGA1064_PIX_CLK_CTL, ucTempByte); 844a31a186aSmrg 845a31a186aSmrg // Reset dotclock rate bit. 846a31a186aSmrg OUTREG8(MGAREG_SEQ_INDEX, 1); 847a31a186aSmrg ucTempByte = INREG8(MGAREG_SEQ_DATA); 848a31a186aSmrg OUTREG8(MGAREG_SEQ_DATA, ucTempByte & ~0x8); 849a31a186aSmrg 850a31a186aSmrg // Set pixclkdis to 0 and pixplldn to 0 851a31a186aSmrg ucTempByte = inMGAdac(MGA1064_PIX_CLK_CTL); 852a31a186aSmrg ucTempByte &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; 853a31a186aSmrg ucTempByte &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; 854a31a186aSmrg outMGAdac(MGA1064_PIX_CLK_CTL, ucTempByte); 855a31a186aSmrg 856a31a186aSmrg // Poll VCount. If it increments twice inside 150us, 857a31a186aSmrg // we assume that the PLL has locked. 858a31a186aSmrg ulLoopCount = 0; 859a31a186aSmrg ulVCount = INREG(MGAREG_VCOUNT); 860a31a186aSmrg 861a31a186aSmrg while(ulLoopCount < 30 && ucPLLLocked == FALSE) 862a31a186aSmrg { 863a31a186aSmrg ulTempCount = INREG(MGAREG_VCOUNT); 864a31a186aSmrg 865a31a186aSmrg if(ulTempCount < ulVCount) 866a31a186aSmrg { 867a31a186aSmrg ulVCount = 0; 868a31a186aSmrg } 869a31a186aSmrg if ((ucTempByte - ulVCount) > 2) 870a31a186aSmrg { 871a31a186aSmrg ucPLLLocked = TRUE; 872a31a186aSmrg } 873a31a186aSmrg else 874a31a186aSmrg { 875a31a186aSmrg usleep(5); 876a31a186aSmrg } 877a31a186aSmrg ulLoopCount++; 878a31a186aSmrg } 879a31a186aSmrg ulLockCheckIterations++; 880a31a186aSmrg } 881a31a186aSmrg} 882a31a186aSmrg 883fe5e51b7Smrg/** 884fe5e51b7Smrg * Calculate the PLL settings (m, n, p, s). 885fe5e51b7Smrg * 886fe5e51b7Smrg * For more information, refer to the Matrox "MGA1064SG Developer 887fe5e51b7Smrg * Specification" (document 10524-MS-0100). chapter 5.7.8. "PLLs Clocks 888fe5e51b7Smrg * Generators" 889fe5e51b7Smrg * 890fe5e51b7Smrg * \param f_out Desired clock frequency, measured in kHz. 891fe5e51b7Smrg * \param best_m Value of PLL 'm' register. 892fe5e51b7Smrg * \param best_n Value of PLL 'n' register. 893fe5e51b7Smrg * \param p Value of PLL 'p' register. 894fe5e51b7Smrg * \param s Value of PLL 's' filter register (pix pll clock only). 895fe5e51b7Smrg */ 896fe5e51b7Smrg 897fe5e51b7Smrgstatic void 898fe5e51b7SmrgMGAGCalcClock ( ScrnInfoPtr pScrn, long f_out, 899fe5e51b7Smrg int *best_m, int *best_n, int *p, int *s ) 900fe5e51b7Smrg{ 901fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 902fe5e51b7Smrg int m, n; 903fe5e51b7Smrg double f_vco; 904fe5e51b7Smrg double m_err, calc_f; 905fe5e51b7Smrg const double ref_freq = (double) pMga->bios.pll_ref_freq; 906fe5e51b7Smrg const int feed_div_max = 127; 907fe5e51b7Smrg const int in_div_min = 1; 908fe5e51b7Smrg const int post_div_max = 7; 909fe5e51b7Smrg int feed_div_min; 910fe5e51b7Smrg int in_div_max; 911fe5e51b7Smrg 912fe5e51b7Smrg 913fe5e51b7Smrg switch( pMga->Chipset ) 914fe5e51b7Smrg { 915fe5e51b7Smrg case PCI_CHIP_MGA1064: 916fe5e51b7Smrg feed_div_min = 100; 917fe5e51b7Smrg in_div_max = 31; 918fe5e51b7Smrg break; 919fe5e51b7Smrg case PCI_CHIP_MGAG400: 920fe5e51b7Smrg case PCI_CHIP_MGAG550: 921fe5e51b7Smrg feed_div_min = 7; 922fe5e51b7Smrg in_div_max = 31; 923fe5e51b7Smrg break; 924fe5e51b7Smrg case PCI_CHIP_MGAG200_SE_A_PCI: 925fe5e51b7Smrg case PCI_CHIP_MGAG200_SE_B_PCI: 926fe5e51b7Smrg case PCI_CHIP_MGAG100: 927fe5e51b7Smrg case PCI_CHIP_MGAG100_PCI: 928fe5e51b7Smrg case PCI_CHIP_MGAG200: 929fe5e51b7Smrg case PCI_CHIP_MGAG200_PCI: 930fe5e51b7Smrg default: 931fe5e51b7Smrg feed_div_min = 7; 932fe5e51b7Smrg in_div_max = 6; 933fe5e51b7Smrg break; 934fe5e51b7Smrg } 935fe5e51b7Smrg 936fe5e51b7Smrg /* Make sure that f_min <= f_out */ 937fe5e51b7Smrg if ( f_out < ( pMga->bios.pixel.min_freq / 8)) 938fe5e51b7Smrg f_out = pMga->bios.pixel.min_freq / 8; 939fe5e51b7Smrg 940fe5e51b7Smrg /* 941fe5e51b7Smrg * f_pll = f_vco / (p+1) 942fe5e51b7Smrg * Choose p so that 943fe5e51b7Smrg * pMga->bios.pixel.min_freq <= f_vco <= pMga->bios.pixel.max_freq 944fe5e51b7Smrg * we don't have to bother checking for this maximum limit. 945fe5e51b7Smrg */ 946fe5e51b7Smrg f_vco = ( double ) f_out; 947fe5e51b7Smrg for ( *p = 0; *p <= post_div_max && f_vco < pMga->bios.pixel.min_freq; 948fe5e51b7Smrg *p = *p * 2 + 1, f_vco *= 2.0); 949fe5e51b7Smrg 950fe5e51b7Smrg /* Initial amount of error for frequency maximum */ 951fe5e51b7Smrg m_err = f_out; 952fe5e51b7Smrg 953fe5e51b7Smrg /* Search for the different values of ( m ) */ 954fe5e51b7Smrg for ( m = in_div_min ; m <= in_div_max ; m++ ) 955fe5e51b7Smrg { 956fe5e51b7Smrg /* see values of ( n ) which we can't use */ 957fe5e51b7Smrg for ( n = feed_div_min; n <= feed_div_max; n++ ) 958fe5e51b7Smrg { 959fbbb26a6Schristos double av; 960fe5e51b7Smrg calc_f = ref_freq * (n + 1) / (m + 1) ; 961fe5e51b7Smrg 962fe5e51b7Smrg /* 963fe5e51b7Smrg * Pick the closest frequency. 964fe5e51b7Smrg */ 96581f79626Smrg if ( fabs(calc_f - f_vco) < m_err ) { 96681f79626Smrg m_err = fabs(calc_f - f_vco); 967fe5e51b7Smrg *best_m = m; 968fe5e51b7Smrg *best_n = n; 969fe5e51b7Smrg } 970fe5e51b7Smrg } 971fe5e51b7Smrg } 972fe5e51b7Smrg 973fe5e51b7Smrg /* Now all the calculations can be completed */ 974fe5e51b7Smrg f_vco = ref_freq * (*best_n + 1) / (*best_m + 1); 975fe5e51b7Smrg 976fe5e51b7Smrg /* Adjustments for filtering pll feed back */ 977fe5e51b7Smrg if ( (50000.0 <= f_vco) 978fe5e51b7Smrg && (f_vco < 100000.0) ) 979fe5e51b7Smrg *s = 0; 980fe5e51b7Smrg if ( (100000.0 <= f_vco) 981fe5e51b7Smrg && (f_vco < 140000.0) ) 982fe5e51b7Smrg *s = 1; 983fe5e51b7Smrg if ( (140000.0 <= f_vco) 984fe5e51b7Smrg && (f_vco < 180000.0) ) 985fe5e51b7Smrg *s = 2; 986fe5e51b7Smrg if ( (180000.0 <= f_vco) ) 987fe5e51b7Smrg *s = 3; 988fe5e51b7Smrg 989fe5e51b7Smrg#ifdef DEBUG 990fe5e51b7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 991fe5e51b7Smrg "f_out_requ =%ld f_pll_real=%.1f f_vco=%.1f n=0x%x m=0x%x p=0x%x s=0x%x\n", 992fe5e51b7Smrg f_out, (f_vco / (*p + 1)), f_vco, *best_n, *best_m, *p, *s ); 993fe5e51b7Smrg#endif 994fe5e51b7Smrg} 995fe5e51b7Smrg 996fe5e51b7Smrg/* 997fe5e51b7Smrg * MGAGSetPCLK - Set the pixel (PCLK) clock. 998fe5e51b7Smrg */ 999fe5e51b7Smrgstatic void 1000fe5e51b7SmrgMGAGSetPCLK( ScrnInfoPtr pScrn, long f_out ) 1001fe5e51b7Smrg{ 1002fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1003fe5e51b7Smrg MGARegPtr pReg = &pMga->ModeReg; 1004fe5e51b7Smrg 1005fe5e51b7Smrg /* Pixel clock values */ 1006fe5e51b7Smrg int m, n, p, s; 1007eda3803bSmrg m = n = p = s = 0; 1008fe5e51b7Smrg 1009fe5e51b7Smrg if(MGAISGx50(pMga)) { 1010fe5e51b7Smrg pReg->Clock = f_out; 1011493f84f4Smrg if (pMga->Chipset == PCI_CHIP_MGAG550) { 1012493f84f4Smrg if (f_out < 45000) { 1013493f84f4Smrg pReg->Pan_Ctl = 0x00; 1014493f84f4Smrg } else if (f_out < 55000) { 1015493f84f4Smrg pReg->Pan_Ctl = 0x08; 1016493f84f4Smrg } else if (f_out < 70000) { 1017493f84f4Smrg pReg->Pan_Ctl = 0x10; 1018493f84f4Smrg } else if (f_out < 85000) { 1019493f84f4Smrg pReg->Pan_Ctl = 0x18; 1020493f84f4Smrg } else if (f_out < 100000) { 1021493f84f4Smrg pReg->Pan_Ctl = 0x20; 1022493f84f4Smrg } else if (f_out < 115000) { 1023493f84f4Smrg pReg->Pan_Ctl = 0x28; 1024493f84f4Smrg } else if (f_out < 125000) { 1025493f84f4Smrg pReg->Pan_Ctl = 0x30; 1026493f84f4Smrg } else { 1027493f84f4Smrg pReg->Pan_Ctl = 0x38; 1028493f84f4Smrg } 1029493f84f4Smrg } else { 1030493f84f4Smrg if (f_out < 45000) { 1031493f84f4Smrg pReg->Pan_Ctl = 0x00; 1032493f84f4Smrg } else if (f_out < 65000) { 1033493f84f4Smrg pReg->Pan_Ctl = 0x08; 1034493f84f4Smrg } else if (f_out < 85000) { 1035493f84f4Smrg pReg->Pan_Ctl = 0x10; 1036493f84f4Smrg } else if (f_out < 105000) { 1037493f84f4Smrg pReg->Pan_Ctl = 0x18; 1038493f84f4Smrg } else if (f_out < 135000) { 1039493f84f4Smrg pReg->Pan_Ctl = 0x20; 1040493f84f4Smrg } else if (f_out < 160000) { 1041493f84f4Smrg pReg->Pan_Ctl = 0x28; 1042493f84f4Smrg } else if (f_out < 175000) { 1043493f84f4Smrg pReg->Pan_Ctl = 0x30; 1044493f84f4Smrg } else { 1045493f84f4Smrg pReg->Pan_Ctl = 0x38; 1046493f84f4Smrg } 1047493f84f4Smrg } 1048fe5e51b7Smrg return; 1049fe5e51b7Smrg } 1050fe5e51b7Smrg 1051fe5e51b7Smrg if (pMga->is_G200SE) { 10526f68ce78Smrg if (pMga->reg_1e24 >= 0x04) { 10536f68ce78Smrg MGAG200E4ComputePLLParam(pScrn, f_out, &m, &n, &p); 10546f68ce78Smrg } else { 10556f68ce78Smrg MGAG200SEComputePLLParam(pScrn, f_out, &m, &n, &p); 10566f68ce78Smrg } 1057fe5e51b7Smrg 1058fe5e51b7Smrg pReg->DacRegs[ MGA1064_PIX_PLLC_M ] = m; 1059fe5e51b7Smrg pReg->DacRegs[ MGA1064_PIX_PLLC_N ] = n; 1060fe5e51b7Smrg pReg->DacRegs[ MGA1064_PIX_PLLC_P ] = p; 1061eda3803bSmrg } else if (pMga->is_G200EV) { 1062eda3803bSmrg MGAG200EVComputePLLParam(pScrn, f_out, &m, &n, &p); 1063eda3803bSmrg 1064eda3803bSmrg pReg->PllM = m; 1065eda3803bSmrg pReg->PllN = n; 1066eda3803bSmrg pReg->PllP = p; 1067eda3803bSmrg } else if (pMga->is_G200WB) { 10686f68ce78Smrg if (pMga->Chipset == PCI_CHIP_MGAG200_EW3_PCI) 10696f68ce78Smrg { 10706f68ce78Smrg MGAG200EW3ComputePLLParam(pScrn, f_out, &m, &n, &p); 10716f68ce78Smrg } 10726f68ce78Smrg else 10736f68ce78Smrg { 10746f68ce78Smrg MGAG200WBComputePLLParam(pScrn, f_out, &m, &n, &p); 10756f68ce78Smrg } 1076eda3803bSmrg 1077a31a186aSmrg pReg->PllM = m; 1078a31a186aSmrg pReg->PllN = n; 1079a31a186aSmrg pReg->PllP = p; 1080a31a186aSmrg } else if (pMga->is_G200EH) { 108181f79626Smrg if (pMga->Chipset == PCI_CHIP_MGAG200_EH3_PCI) 108281f79626Smrg { 108381f79626Smrg MGAG200EH3ComputePLLParam(pScrn, f_out, &m, &n, &p); 108481f79626Smrg } 108581f79626Smrg else 108681f79626Smrg { 108781f79626Smrg MGAG200EHComputePLLParam(pScrn, f_out, &m, &n, &p); 108881f79626Smrg } 1089a31a186aSmrg 1090eda3803bSmrg pReg->PllM = m; 1091eda3803bSmrg pReg->PllN = n; 10920bb88ba4Smrg pReg->PllP = p; 10930bb88ba4Smrg } else if (pMga->is_G200ER) { 10940bb88ba4Smrg MGAG200ERComputePLLParam(pScrn, f_out, &m, &n, &p); 10950bb88ba4Smrg pReg->PllM = m; 10960bb88ba4Smrg pReg->PllN = n; 10970bb88ba4Smrg pReg->PllP = p; 10980bb88ba4Smrg } else { 1099fe5e51b7Smrg /* Do the calculations for m, n, p and s */ 1100fe5e51b7Smrg MGAGCalcClock( pScrn, f_out, &m, &n, &p, &s ); 1101fe5e51b7Smrg 1102fe5e51b7Smrg /* Values for the pixel clock PLL registers */ 1103fe5e51b7Smrg pReg->DacRegs[ MGA1064_PIX_PLLC_M ] = m & 0x1F; 1104fe5e51b7Smrg pReg->DacRegs[ MGA1064_PIX_PLLC_N ] = n & 0x7F; 1105fe5e51b7Smrg pReg->DacRegs[ MGA1064_PIX_PLLC_P ] = (p & 0x07) | 1106fe5e51b7Smrg ((s & 0x03) << 3); 1107fe5e51b7Smrg } 1108fe5e51b7Smrg} 1109fe5e51b7Smrg 1110fe5e51b7Smrg/* 1111fe5e51b7Smrg * MGAGInit 1112fe5e51b7Smrg */ 1113fe5e51b7Smrgstatic Bool 1114fe5e51b7SmrgMGAGInit(ScrnInfoPtr pScrn, DisplayModePtr mode) 1115fe5e51b7Smrg{ 1116fe5e51b7Smrg /* 1117fe5e51b7Smrg * initial values of the DAC registers 1118fe5e51b7Smrg */ 1119fe5e51b7Smrg const static unsigned char initDAC[] = { 1120fe5e51b7Smrg /* 0x00: */ 0, 0, 0, 0, 0, 0, 0x00, 0, 1121fe5e51b7Smrg /* 0x08: */ 0, 0, 0, 0, 0, 0, 0, 0, 1122fe5e51b7Smrg /* 0x10: */ 0, 0, 0, 0, 0, 0, 0, 0, 1123fe5e51b7Smrg /* 0x18: */ 0x00, 0, 0xC9, 0xFF, 0xBF, 0x20, 0x1F, 0x20, 1124fe5e51b7Smrg /* 0x20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1125fe5e51b7Smrg /* 0x28: */ 0x00, 0x00, 0x00, 0x00, 0, 0, 0, 0x40, 1126fe5e51b7Smrg /* 0x30: */ 0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83, 1127fe5e51b7Smrg /* 0x38: */ 0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A, 1128fe5e51b7Smrg /* 0x40: */ 0, 0, 0, 0, 0, 0, 0, 0, 1129fe5e51b7Smrg /* 0x48: */ 0, 0, 0, 0, 0, 0, 0, 0 1130fe5e51b7Smrg }; 1131fe5e51b7Smrg 1132fe5e51b7Smrg int i; 1133fe5e51b7Smrg int hd, hs, he, ht, vd, vs, ve, vt, wd; 1134fe5e51b7Smrg int BppShift; 1135fe5e51b7Smrg MGAPtr pMga; 1136fe5e51b7Smrg MGARegPtr pReg; 1137fe5e51b7Smrg vgaRegPtr pVga; 1138fe5e51b7Smrg MGAFBLayout *pLayout; 1139fe5e51b7Smrg xMODEINFO ModeInfo; 1140fe5e51b7Smrg 1141fe5e51b7Smrg ModeInfo.ulDispWidth = mode->HDisplay; 1142fe5e51b7Smrg ModeInfo.ulDispHeight = mode->VDisplay; 1143fe5e51b7Smrg ModeInfo.ulFBPitch = mode->HDisplay; 1144fe5e51b7Smrg ModeInfo.ulBpp = pScrn->bitsPerPixel; 1145fe5e51b7Smrg ModeInfo.flSignalMode = 0; 1146fe5e51b7Smrg ModeInfo.ulPixClock = mode->Clock; 1147fe5e51b7Smrg ModeInfo.ulHFPorch = mode->HSyncStart - mode->HDisplay; 1148fe5e51b7Smrg ModeInfo.ulHSync = mode->HSyncEnd - mode->HSyncStart; 1149fe5e51b7Smrg ModeInfo.ulHBPorch = mode->HTotal - mode->HSyncEnd; 1150fe5e51b7Smrg ModeInfo.ulVFPorch = mode->VSyncStart - mode->VDisplay; 1151fe5e51b7Smrg ModeInfo.ulVSync = mode->VSyncEnd - mode->VSyncStart; 1152fe5e51b7Smrg ModeInfo.ulVBPorch = mode->VTotal - mode->VSyncEnd; 1153fe5e51b7Smrg 1154fe5e51b7Smrg pMga = MGAPTR(pScrn); 1155fe5e51b7Smrg pReg = &pMga->ModeReg; 1156fe5e51b7Smrg pVga = &VGAHWPTR(pScrn)->ModeReg; 1157fe5e51b7Smrg pLayout = &pMga->CurrentLayout; 1158fe5e51b7Smrg 1159fe5e51b7Smrg BppShift = pMga->BppShifts[(pLayout->bitsPerPixel >> 3) - 1]; 1160fe5e51b7Smrg 1161fe5e51b7Smrg MGA_NOT_HAL( 1162fe5e51b7Smrg /* Allocate the DacRegs space if not done already */ 1163fe5e51b7Smrg if (pReg->DacRegs == NULL) { 1164fe5e51b7Smrg pReg->DacRegs = xnfcalloc(DACREGSIZE, 1); 1165fe5e51b7Smrg } 1166fe5e51b7Smrg for (i = 0; i < DACREGSIZE; i++) { 1167fe5e51b7Smrg pReg->DacRegs[i] = initDAC[i]; 1168fe5e51b7Smrg } 1169fe5e51b7Smrg ); /* MGA_NOT_HAL */ 1170fe5e51b7Smrg 1171fe5e51b7Smrg switch(pMga->Chipset) 1172fe5e51b7Smrg { 1173fe5e51b7Smrg case PCI_CHIP_MGA1064: 1174fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x04; 1175fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x44; 1176fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18; 1177fe5e51b7Smrg pReg->Option = 0x5F094F21; 1178fe5e51b7Smrg pReg->Option2 = 0x00000000; 1179fe5e51b7Smrg break; 1180fe5e51b7Smrg case PCI_CHIP_MGAG100: 1181fe5e51b7Smrg case PCI_CHIP_MGAG100_PCI: 1182fe5e51b7Smrg pReg->DacRegs[MGA1064_VREF_CTL] = 0x03; 1183fe5e51b7Smrg 1184fe5e51b7Smrg if(pMga->HasSDRAM) { 1185fe5e51b7Smrg if(pMga->OverclockMem) { 1186fe5e51b7Smrg /* 220 Mhz */ 1187fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x06; 1188fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x38; 1189fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18; 1190fe5e51b7Smrg } else { 1191fe5e51b7Smrg /* 203 Mhz */ 1192fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x01; 1193fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x0E; 1194fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18; 1195fe5e51b7Smrg } 1196fe5e51b7Smrg pReg->Option = 0x404991a9; 1197fe5e51b7Smrg } else { 1198fe5e51b7Smrg if(pMga->OverclockMem) { 1199fe5e51b7Smrg /* 143 Mhz */ 1200fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x06; 1201fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x24; 1202fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x10; 1203fe5e51b7Smrg } else { 1204fe5e51b7Smrg /* 124 Mhz */ 1205fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x04; 1206fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x16; 1207fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x08; 1208fe5e51b7Smrg } 1209fe5e51b7Smrg pReg->Option = 0x4049d121; 1210fe5e51b7Smrg } 1211fe5e51b7Smrg pReg->Option2 = 0x0000007; 1212fe5e51b7Smrg break; 1213fe5e51b7Smrg case PCI_CHIP_MGAG400: 1214fe5e51b7Smrg case PCI_CHIP_MGAG550: 1215fe5e51b7Smrg if (MGAISGx50(pMga)) 1216fe5e51b7Smrg break; 1217fe5e51b7Smrg 1218fe5e51b7Smrg if(pMga->Dac.maxPixelClock == 360000) { /* G400 MAX */ 1219fe5e51b7Smrg if(pMga->OverclockMem) { 1220fe5e51b7Smrg /* 150/200 */ 1221fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x05; 1222fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x42; 1223fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18; 1224fe5e51b7Smrg pReg->Option3 = 0x019B8419; 1225fe5e51b7Smrg pReg->Option = 0x50574120; 1226fe5e51b7Smrg } else { 1227fe5e51b7Smrg /* 125/166 */ 1228fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x02; 1229fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x1B; 1230fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18; 1231fe5e51b7Smrg pReg->Option3 = 0x019B8419; 1232fe5e51b7Smrg pReg->Option = 0x5053C120; 1233fe5e51b7Smrg } 1234fe5e51b7Smrg } else { 1235fe5e51b7Smrg if(pMga->OverclockMem) { 1236fe5e51b7Smrg /* 125/166 */ 1237fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x02; 1238fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x1B; 1239fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18; 1240fe5e51b7Smrg pReg->Option3 = 0x019B8419; 1241fe5e51b7Smrg pReg->Option = 0x5053C120; 1242fe5e51b7Smrg } else { 1243fe5e51b7Smrg /* 110/166 */ 1244fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x13; 1245fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x7A; 1246fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x08; 1247fe5e51b7Smrg pReg->Option3 = 0x0190a421; 1248fe5e51b7Smrg pReg->Option = 0x50044120; 1249fe5e51b7Smrg } 1250fe5e51b7Smrg } 1251fe5e51b7Smrg if(pMga->HasSDRAM) 1252fe5e51b7Smrg pReg->Option &= ~(1 << 14); 1253fe5e51b7Smrg pReg->Option2 = 0x01003000; 1254fe5e51b7Smrg break; 1255fe5e51b7Smrg case PCI_CHIP_MGAG200_SE_A_PCI: 1256fe5e51b7Smrg case PCI_CHIP_MGAG200_SE_B_PCI: 1257fe5e51b7Smrg pReg->DacRegs[ MGA1064_VREF_CTL ] = 0x03; 1258fe5e51b7Smrg pReg->DacRegs[MGA1064_PIX_CLK_CTL] = 1259fe5e51b7Smrg MGA1064_PIX_CLK_CTL_SEL_PLL; 1260fe5e51b7Smrg 1261fe5e51b7Smrg pReg->DacRegs[MGA1064_MISC_CTL] = 1262fe5e51b7Smrg MGA1064_MISC_CTL_DAC_EN | 1263fe5e51b7Smrg MGA1064_MISC_CTL_VGA8 | 1264fe5e51b7Smrg MGA1064_MISC_CTL_DAC_RAM_CS; 1265fe5e51b7Smrg 1266fe5e51b7Smrg if (pMga->HasSDRAM) 1267fe5e51b7Smrg pReg->Option = 0x40049120; 1268fe5e51b7Smrg pReg->Option2 = 0x00008000; 1269fe5e51b7Smrg break; 1270eda3803bSmrg 1271eda3803bSmrg case PCI_CHIP_MGAG200_WINBOND_PCI: 12726f68ce78Smrg case PCI_CHIP_MGAG200_EW3_PCI: 1273eda3803bSmrg pReg->DacRegs[MGA1064_VREF_CTL] = 0x07; 1274eda3803bSmrg pReg->Option = 0x41049120; 1275eda3803bSmrg pReg->Option2 = 0x0000b000; 1276eda3803bSmrg break; 1277eda3803bSmrg 1278eda3803bSmrg case PCI_CHIP_MGAG200_EV_PCI: 1279eda3803bSmrg pReg->DacRegs[MGA1064_PIX_CLK_CTL] = 1280eda3803bSmrg MGA1064_PIX_CLK_CTL_SEL_PLL; 1281eda3803bSmrg 1282eda3803bSmrg pReg->DacRegs[MGA1064_MISC_CTL] = 1283eda3803bSmrg MGA1064_MISC_CTL_VGA8 | 1284eda3803bSmrg MGA1064_MISC_CTL_DAC_RAM_CS; 1285eda3803bSmrg 1286eda3803bSmrg pReg->Option = 0x00000120; 1287eda3803bSmrg pReg->Option2 = 0x0000b000; 1288eda3803bSmrg break; 1289eda3803bSmrg 12900bb88ba4Smrg case PCI_CHIP_MGAG200_ER_PCI: 12910bb88ba4Smrg pReg->Dac_Index90 = 0; 12920bb88ba4Smrg break; 12930bb88ba4Smrg 1294a31a186aSmrg case PCI_CHIP_MGAG200_EH_PCI: 129581f79626Smrg case PCI_CHIP_MGAG200_EH3_PCI: 1296a31a186aSmrg pReg->DacRegs[MGA1064_MISC_CTL] = 1297a31a186aSmrg MGA1064_MISC_CTL_VGA8 | 1298a31a186aSmrg MGA1064_MISC_CTL_DAC_RAM_CS; 1299a31a186aSmrg 1300a31a186aSmrg pReg->Option = 0x00000120; 1301a31a186aSmrg pReg->Option2 = 0x0000b000; 1302a31a186aSmrg break; 1303a31a186aSmrg 1304fe5e51b7Smrg case PCI_CHIP_MGAG200: 1305fe5e51b7Smrg case PCI_CHIP_MGAG200_PCI: 1306fe5e51b7Smrg default: 1307fe5e51b7Smrg if(pMga->OverclockMem) { 1308fe5e51b7Smrg /* 143 Mhz */ 1309fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x06; 1310fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x24; 1311fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x10; 1312fe5e51b7Smrg } else { 1313fe5e51b7Smrg /* 124 Mhz */ 1314fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x04; 1315fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x2D; 1316fe5e51b7Smrg pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x19; 1317fe5e51b7Smrg } 1318fe5e51b7Smrg pReg->Option2 = 0x00008000; 1319fe5e51b7Smrg if(pMga->HasSDRAM) 1320fe5e51b7Smrg pReg->Option = 0x40499121; 1321fe5e51b7Smrg else 1322fe5e51b7Smrg pReg->Option = 0x4049cd21; 1323fe5e51b7Smrg break; 1324fe5e51b7Smrg } 1325fe5e51b7Smrg 1326fe5e51b7Smrg MGA_NOT_HAL( 1327fe5e51b7Smrg /* must always have the pci retries on but rely on 1328fe5e51b7Smrg polling to keep them from occuring */ 1329fe5e51b7Smrg pReg->Option &= ~0x20000000; 1330fe5e51b7Smrg 1331fe5e51b7Smrg switch(pLayout->bitsPerPixel) 1332fe5e51b7Smrg { 1333fe5e51b7Smrg case 8: 1334fe5e51b7Smrg pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_8bits; 1335fe5e51b7Smrg break; 1336fe5e51b7Smrg case 16: 1337fe5e51b7Smrg pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_16bits; 1338fe5e51b7Smrg if ( (pLayout->weight.red == 5) && (pLayout->weight.green == 5) 1339fe5e51b7Smrg && (pLayout->weight.blue == 5) ) { 1340fe5e51b7Smrg pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_15bits; 1341fe5e51b7Smrg } 1342fe5e51b7Smrg break; 1343fe5e51b7Smrg case 24: 1344fe5e51b7Smrg pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_24bits; 1345fe5e51b7Smrg break; 1346fe5e51b7Smrg case 32: 1347eda3803bSmrg pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_32_24bits; 1348eda3803bSmrg break; 1349fe5e51b7Smrg default: 1350fe5e51b7Smrg FatalError("MGA: unsupported depth\n"); 1351fe5e51b7Smrg } 1352fe5e51b7Smrg ); /* MGA_NOT_HAL */ 1353fe5e51b7Smrg 1354fe5e51b7Smrg /* 1355fe5e51b7Smrg * This will initialize all of the generic VGA registers. 1356fe5e51b7Smrg */ 1357fe5e51b7Smrg if (!vgaHWInit(pScrn, mode)) 1358fe5e51b7Smrg return(FALSE); 1359fe5e51b7Smrg 1360fe5e51b7Smrg /* 1361fe5e51b7Smrg * Here all of the MGA registers get filled in. 1362fe5e51b7Smrg */ 1363fe5e51b7Smrg hd = (mode->CrtcHDisplay >> 3) - 1; 1364fe5e51b7Smrg hs = (mode->CrtcHSyncStart >> 3) - 1; 1365fe5e51b7Smrg he = (mode->CrtcHSyncEnd >> 3) - 1; 1366fe5e51b7Smrg ht = (mode->CrtcHTotal >> 3) - 1; 1367fe5e51b7Smrg vd = mode->CrtcVDisplay - 1; 1368fe5e51b7Smrg vs = mode->CrtcVSyncStart - 1; 1369fe5e51b7Smrg ve = mode->CrtcVSyncEnd - 1; 1370fe5e51b7Smrg vt = mode->CrtcVTotal - 2; 1371fe5e51b7Smrg 1372fe5e51b7Smrg /* HTOTAL & 0x7 equal to 0x6 in 8bpp or 0x4 in 24bpp causes strange 1373fe5e51b7Smrg * vertical stripes 1374fe5e51b7Smrg */ 1375fe5e51b7Smrg if((ht & 0x07) == 0x06 || (ht & 0x07) == 0x04) 1376fe5e51b7Smrg ht++; 1377fe5e51b7Smrg 1378fe5e51b7Smrg if (pLayout->bitsPerPixel == 24) 1379fe5e51b7Smrg wd = (pLayout->displayWidth * 3) >> (4 - BppShift); 1380fe5e51b7Smrg else 1381fe5e51b7Smrg wd = pLayout->displayWidth >> (4 - BppShift); 1382fe5e51b7Smrg 1383fe5e51b7Smrg pReg->ExtVga[0] = 0; 1384fe5e51b7Smrg pReg->ExtVga[5] = 0; 1385fe5e51b7Smrg 1386fe5e51b7Smrg if (mode->Flags & V_INTERLACE) 1387fe5e51b7Smrg { 1388fe5e51b7Smrg pReg->ExtVga[0] = 0x80; 1389fe5e51b7Smrg pReg->ExtVga[5] = (hs + he - ht) >> 1; 1390fe5e51b7Smrg wd <<= 1; 1391fe5e51b7Smrg vt &= 0xFFFE; 1392fe5e51b7Smrg } 1393fe5e51b7Smrg 1394fe5e51b7Smrg pReg->ExtVga[0] |= (wd & 0x300) >> 4; 1395fe5e51b7Smrg pReg->ExtVga[1] = (((ht - 4) & 0x100) >> 8) | 1396fe5e51b7Smrg ((hd & 0x100) >> 7) | 1397fe5e51b7Smrg ((hs & 0x100) >> 6) | 1398fe5e51b7Smrg (ht & 0x40); 1399fe5e51b7Smrg pReg->ExtVga[2] = ((vt & 0xc00) >> 10) | 1400fe5e51b7Smrg ((vd & 0x400) >> 8) | 1401fe5e51b7Smrg ((vd & 0xc00) >> 7) | 1402fe5e51b7Smrg ((vs & 0xc00) >> 5) | 1403fe5e51b7Smrg ((vd & 0x400) >> 3); /* linecomp */ 1404fe5e51b7Smrg if (pLayout->bitsPerPixel == 24) 1405fe5e51b7Smrg pReg->ExtVga[3] = (((1 << BppShift) * 3) - 1) | 0x80; 1406fe5e51b7Smrg else 1407fe5e51b7Smrg pReg->ExtVga[3] = ((1 << BppShift) - 1) | 0x80; 1408fe5e51b7Smrg 1409eda3803bSmrg pReg->ExtVga[4] = 0; 1410eda3803bSmrg 1411eda3803bSmrg if (pMga->is_G200WB){ 1412eda3803bSmrg pReg->ExtVga[1] |= 0x88; 1413eda3803bSmrg } 14146f68ce78Smrg pReg->ExtVga_MgaReq = 0x05; 1415fe5e51b7Smrg 1416fe5e51b7Smrg pVga->CRTC[0] = ht - 4; 1417fe5e51b7Smrg pVga->CRTC[1] = hd; 1418fe5e51b7Smrg pVga->CRTC[2] = hd; 1419fe5e51b7Smrg pVga->CRTC[3] = (ht & 0x1F) | 0x80; 1420fe5e51b7Smrg pVga->CRTC[4] = hs; 1421fe5e51b7Smrg pVga->CRTC[5] = ((ht & 0x20) << 2) | (he & 0x1F); 1422fe5e51b7Smrg pVga->CRTC[6] = vt & 0xFF; 1423fe5e51b7Smrg pVga->CRTC[7] = ((vt & 0x100) >> 8 ) | 1424fe5e51b7Smrg ((vd & 0x100) >> 7 ) | 1425fe5e51b7Smrg ((vs & 0x100) >> 6 ) | 1426fe5e51b7Smrg ((vd & 0x100) >> 5 ) | 1427fe5e51b7Smrg ((vd & 0x100) >> 4 ) | /* linecomp */ 1428fe5e51b7Smrg ((vt & 0x200) >> 4 ) | 1429fe5e51b7Smrg ((vd & 0x200) >> 3 ) | 1430fe5e51b7Smrg ((vs & 0x200) >> 2 ); 1431fe5e51b7Smrg pVga->CRTC[9] = ((vd & 0x200) >> 4) | 1432fe5e51b7Smrg ((vd & 0x200) >> 3); /* linecomp */ 1433fe5e51b7Smrg pVga->CRTC[16] = vs & 0xFF; 1434fe5e51b7Smrg pVga->CRTC[17] = (ve & 0x0F) | 0x20; 1435fe5e51b7Smrg pVga->CRTC[18] = vd & 0xFF; 1436fe5e51b7Smrg pVga->CRTC[19] = wd & 0xFF; 1437fe5e51b7Smrg pVga->CRTC[21] = vd & 0xFF; 1438fe5e51b7Smrg pVga->CRTC[22] = (vt + 1) & 0xFF; 1439fe5e51b7Smrg pVga->CRTC[24] = vd & 0xFF; /* linecomp */ 1440fe5e51b7Smrg 1441fe5e51b7Smrg MGA_NOT_HAL(pReg->DacRegs[MGA1064_CURSOR_BASE_ADR_LOW] = pMga->FbCursorOffset >> 10); 1442fe5e51b7Smrg MGA_NOT_HAL(pReg->DacRegs[MGA1064_CURSOR_BASE_ADR_HI] = pMga->FbCursorOffset >> 18); 1443fe5e51b7Smrg 1444fe5e51b7Smrg if (pMga->SyncOnGreen) { 1445fe5e51b7Smrg MGA_NOT_HAL( 1446fe5e51b7Smrg pReg->DacRegs[MGA1064_GEN_CTL] &= 1447fe5e51b7Smrg ~MGA1064_GEN_CTL_SYNC_ON_GREEN_DIS; 1448fe5e51b7Smrg ); 1449fe5e51b7Smrg 1450fe5e51b7Smrg pReg->ExtVga[3] |= 0x40; 1451fe5e51b7Smrg } 1452fe5e51b7Smrg 1453fe5e51b7Smrg /* select external clock */ 1454fe5e51b7Smrg pVga->MiscOutReg |= 0x0C; 1455fe5e51b7Smrg 1456fe5e51b7Smrg MGA_NOT_HAL( 1457fe5e51b7Smrg if (mode->Flags & V_DBLSCAN) 1458fe5e51b7Smrg pVga->CRTC[9] |= 0x80; 1459fe5e51b7Smrg 1460fe5e51b7Smrg if(MGAISGx50(pMga)) { 1461fe5e51b7Smrg OUTREG(MGAREG_ZORG, 0); 1462fe5e51b7Smrg } 1463fe5e51b7Smrg 1464fe5e51b7Smrg MGAGSetPCLK(pScrn, mode->Clock); 1465fe5e51b7Smrg ); /* MGA_NOT_HAL */ 1466fe5e51b7Smrg 1467fe5e51b7Smrg /* This disables the VGA memory aperture */ 1468fe5e51b7Smrg pVga->MiscOutReg &= ~0x02; 1469fe5e51b7Smrg 1470fe5e51b7Smrg /* Urgh. Why do we define our own xMODEINFO structure instead 1471fe5e51b7Smrg * of just passing the blinkin' DisplayModePtr? If we're going to 1472fe5e51b7Smrg * just cut'n'paste routines from the HALlib, it would be better 1473fe5e51b7Smrg * just to strip the MacroVision stuff out of the HALlib and release 1474fe5e51b7Smrg * that, surely? 1475fe5e51b7Smrg */ 1476fe5e51b7Smrg /********************* Second Crtc programming **************/ 1477fe5e51b7Smrg /* Writing values to crtc2[] array */ 1478fe5e51b7Smrg if (pMga->SecondCrtc) 1479fe5e51b7Smrg { 1480fe5e51b7Smrg MGACRTC2Get(pScrn, &ModeInfo); 1481fe5e51b7Smrg MGACRTC2GetPitch(pScrn, &ModeInfo); 1482fe5e51b7Smrg MGACRTC2GetDisplayStart(pScrn, &ModeInfo,0,0,0); 1483fe5e51b7Smrg } 1484fe5e51b7Smrg 1485fe5e51b7Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN 1486fe5e51b7Smrg /* Disable byte-swapping for big-endian architectures - the XFree 1487fe5e51b7Smrg driver seems to like a little-endian framebuffer -ReneR */ 1488fe5e51b7Smrg /* pReg->Option |= 0x80000000; */ 1489fe5e51b7Smrg pReg->Option &= ~0x80000000; 1490fe5e51b7Smrg#endif 1491fe5e51b7Smrg 1492fe5e51b7Smrg return(TRUE); 1493fe5e51b7Smrg} 1494fe5e51b7Smrg 1495fe5e51b7Smrg/* 1496fe5e51b7Smrg * MGAGLoadPalette 1497fe5e51b7Smrg */ 1498fe5e51b7Smrg 1499fe5e51b7Smrgstatic void 1500fe5e51b7SmrgMGAPaletteLoadCallback(ScrnInfoPtr pScrn) 1501fe5e51b7Smrg{ 1502fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1503fe5e51b7Smrg MGAPaletteInfo *pal = pMga->palinfo; 1504fe5e51b7Smrg int i; 1505fe5e51b7Smrg 1506fe5e51b7Smrg while (!(INREG8(0x1FDA) & 0x08)); 1507fe5e51b7Smrg 1508fe5e51b7Smrg for(i = 0; i < 256; i++) { 1509fe5e51b7Smrg if(pal->update) { 1510fe5e51b7Smrg outMGAdreg(MGA1064_WADR_PAL, i); 1511fe5e51b7Smrg outMGAdreg(MGA1064_COL_PAL, pal->red); 1512fe5e51b7Smrg outMGAdreg(MGA1064_COL_PAL, pal->green); 1513fe5e51b7Smrg outMGAdreg(MGA1064_COL_PAL, pal->blue); 1514fe5e51b7Smrg pal->update = FALSE; 1515fe5e51b7Smrg } 1516fe5e51b7Smrg pal++; 1517fe5e51b7Smrg } 1518fe5e51b7Smrg pMga->PaletteLoadCallback = NULL; 1519fe5e51b7Smrg} 1520fe5e51b7Smrg 1521fe5e51b7Smrgvoid MGAGLoadPalette( 1522fe5e51b7Smrg ScrnInfoPtr pScrn, 1523fe5e51b7Smrg int numColors, 1524fe5e51b7Smrg int *indices, 1525fe5e51b7Smrg LOCO *colors, 1526fe5e51b7Smrg VisualPtr pVisual 1527fe5e51b7Smrg){ 1528fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1529fe5e51b7Smrg 1530fe5e51b7Smrg if(pMga->Chipset == PCI_CHIP_MGAG400 || pMga->Chipset == PCI_CHIP_MGAG550){ 1531fe5e51b7Smrg /* load them at the retrace in the block handler instead to 1532fe5e51b7Smrg work around some problems with static on the screen */ 1533fe5e51b7Smrg while(numColors--) { 1534fe5e51b7Smrg pMga->palinfo[*indices].update = TRUE; 1535fe5e51b7Smrg pMga->palinfo[*indices].red = colors[*indices].red; 1536fe5e51b7Smrg pMga->palinfo[*indices].green = colors[*indices].green; 1537fe5e51b7Smrg pMga->palinfo[*indices].blue = colors[*indices].blue; 1538fe5e51b7Smrg indices++; 1539fe5e51b7Smrg } 1540fe5e51b7Smrg pMga->PaletteLoadCallback = MGAPaletteLoadCallback; 1541fe5e51b7Smrg return; 1542fe5e51b7Smrg } else { 1543fe5e51b7Smrg while(numColors--) { 1544fe5e51b7Smrg outMGAdreg(MGA1064_WADR_PAL, *indices); 1545fe5e51b7Smrg outMGAdreg(MGA1064_COL_PAL, colors[*indices].red); 1546fe5e51b7Smrg outMGAdreg(MGA1064_COL_PAL, colors[*indices].green); 1547fe5e51b7Smrg outMGAdreg(MGA1064_COL_PAL, colors[*indices].blue); 1548fe5e51b7Smrg indices++; 1549fe5e51b7Smrg } 1550fe5e51b7Smrg } 1551fe5e51b7Smrg} 1552fe5e51b7Smrg 1553fe5e51b7Smrg/* 1554fe5e51b7Smrg * MGAGRestorePalette 1555fe5e51b7Smrg */ 1556fe5e51b7Smrg 1557fe5e51b7Smrgstatic void 1558fe5e51b7SmrgMGAGRestorePalette(ScrnInfoPtr pScrn, unsigned char* pntr) 1559fe5e51b7Smrg{ 1560fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1561fe5e51b7Smrg int i = 768; 1562fe5e51b7Smrg 1563fe5e51b7Smrg outMGAdreg(MGA1064_WADR_PAL, 0x00); 1564fe5e51b7Smrg while(i--) 1565fe5e51b7Smrg outMGAdreg(MGA1064_COL_PAL, *(pntr++)); 1566fe5e51b7Smrg} 1567fe5e51b7Smrg 1568fe5e51b7Smrg/* 1569fe5e51b7Smrg * MGAGSavePalette 1570fe5e51b7Smrg */ 1571fe5e51b7Smrgstatic void 1572fe5e51b7SmrgMGAGSavePalette(ScrnInfoPtr pScrn, unsigned char* pntr) 1573fe5e51b7Smrg{ 1574fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1575fe5e51b7Smrg int i = 768; 1576fe5e51b7Smrg 1577fe5e51b7Smrg outMGAdreg(MGA1064_RADR_PAL, 0x00); 1578fe5e51b7Smrg while(i--) 1579fe5e51b7Smrg *(pntr++) = inMGAdreg(MGA1064_COL_PAL); 1580fe5e51b7Smrg} 1581fe5e51b7Smrg 1582fe5e51b7Smrg/* 1583fe5e51b7Smrg * MGAGRestore 1584fe5e51b7Smrg * 1585fe5e51b7Smrg * This function restores a video mode. It basically writes out all of 1586fe5e51b7Smrg * the registers that have previously been saved. 1587fe5e51b7Smrg */ 1588fe5e51b7Smrgstatic void 1589fe5e51b7SmrgMGAGRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, MGARegPtr mgaReg, 1590fe5e51b7Smrg Bool restoreFonts) 1591fe5e51b7Smrg{ 1592fe5e51b7Smrg int i; 1593fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1594fe5e51b7Smrg CARD32 optionMask; 1595fe5e51b7Smrg 1596eda3803bSmrgMGA_NOT_HAL( 1597eda3803bSmrg if (pMga->is_G200WB) 1598eda3803bSmrg { 1599eda3803bSmrg MGAG200WBPrepareForModeSwitch(pScrn); 1600eda3803bSmrg } 1601eda3803bSmrg); 1602eda3803bSmrg 1603fe5e51b7Smrg /* 1604fe5e51b7Smrg * Pixel Clock needs to be restored regardless if we use 1605fe5e51b7Smrg * HALLib or not. HALlib doesn't do a good job restoring 1606fe5e51b7Smrg * VESA modes. MATROX: hint, hint. 1607fe5e51b7Smrg */ 1608fe5e51b7Smrg if (MGAISGx50(pMga) && mgaReg->Clock) { 1609fe5e51b7Smrg /* 1610fe5e51b7Smrg * With HALlib program only when restoring to console! 1611fe5e51b7Smrg * To test this we check for Clock == 0. 1612fe5e51b7Smrg */ 1613fe5e51b7Smrg MGAG450SetPLLFreq(pScrn, mgaReg->Clock); 1614493f84f4Smrg outMGAdac(MGA1064_PAN_CTL, mgaReg->Pan_Ctl); 1615fe5e51b7Smrg mgaReg->PIXPLLCSaved = FALSE; 1616fe5e51b7Smrg } 1617fe5e51b7Smrg 1618fe5e51b7Smrg if(!pMga->SecondCrtc) { 1619fe5e51b7Smrg /* Do not set the memory config for primary cards as it 1620fe5e51b7Smrg should be correct already. Only on little endian architectures 1621fe5e51b7Smrg since we need to modify the byteswap bit. -ReneR */ 1622fe5e51b7Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN 1623fe5e51b7Smrg optionMask = OPTION1_MASK; 1624fe5e51b7Smrg#else 1625fe5e51b7Smrg optionMask = (pMga->Primary) ? OPTION1_MASK_PRIMARY : OPTION1_MASK; 1626fe5e51b7Smrg#endif 1627fe5e51b7Smrg 1628fe5e51b7SmrgMGA_NOT_HAL( 1629fe5e51b7Smrg /* 1630fe5e51b7Smrg * Code is needed to get things back to bank zero. 1631fe5e51b7Smrg */ 1632fe5e51b7Smrg 1633fe5e51b7Smrg /* restore DAC registers 1634fe5e51b7Smrg * according to the docs we shouldn't write to reserved regs*/ 1635fe5e51b7Smrg for (i = 0; i < DACREGSIZE; i++) { 1636fe5e51b7Smrg if( (i <= 0x03) || 1637fe5e51b7Smrg (i == 0x07) || 1638fe5e51b7Smrg (i == 0x0b) || 1639fe5e51b7Smrg (i == 0x0f) || 1640fe5e51b7Smrg ((i >= 0x13) && (i <= 0x17)) || 1641fe5e51b7Smrg (i == 0x1b) || 1642fe5e51b7Smrg (i == 0x1c) || 1643fe5e51b7Smrg ((i >= 0x1f) && (i <= 0x29)) || 1644fe5e51b7Smrg ((i >= 0x30) && (i <= 0x37)) || 1645fe5e51b7Smrg (MGAISGx50(pMga) && !mgaReg->PIXPLLCSaved && 1646fe5e51b7Smrg ((i == 0x2c) || (i == 0x2d) || (i == 0x2e) || 1647fe5e51b7Smrg (i == 0x4c) || (i == 0x4d) || (i == 0x4e)))) 1648fe5e51b7Smrg continue; 1649fe5e51b7Smrg if (pMga->is_G200SE 1650fe5e51b7Smrg && ((i == 0x2C) || (i == 0x2D) || (i == 0x2E))) 1651fe5e51b7Smrg continue; 1652a31a186aSmrg if ( (pMga->is_G200EV || pMga->is_G200WB || pMga->is_G200EH) && 1653eda3803bSmrg (i >= 0x44) && (i <= 0x4E)) 1654eda3803bSmrg continue; 16550bb88ba4Smrg 1656fe5e51b7Smrg outMGAdac(i, mgaReg->DacRegs[i]); 1657fe5e51b7Smrg } 1658fe5e51b7Smrg 16590bb88ba4Smrg if (pMga->is_G200ER) 16600bb88ba4Smrg { 16610bb88ba4Smrg outMGAdac(0x90, mgaReg->Dac_Index90); 16620bb88ba4Smrg } 16636f68ce78Smrg if (pMga->is_G200SE && (pMga->reg_1e24 >= 0x04)) { 16646f68ce78Smrg outMGAdac( 0x1a, 0x09); 16656f68ce78Smrg usleep(500); 16666f68ce78Smrg outMGAdac( 0x1a, 0x01); 16676f68ce78Smrg } 16686f68ce78Smrg 1669fe5e51b7Smrg if (!MGAISGx50(pMga)) { 1670fe5e51b7Smrg /* restore pci_option register */ 1671fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS 1672fe5e51b7Smrg pci_device_cfg_write_bits(pMga->PciInfo, optionMask, 1673fe5e51b7Smrg mgaReg->Option, PCI_OPTION_REG); 1674fe5e51b7Smrg 1675fe5e51b7Smrg if (pMga->Chipset != PCI_CHIP_MGA1064) { 1676fe5e51b7Smrg pci_device_cfg_write_bits(pMga->PciInfo, OPTION2_MASK, 1677fe5e51b7Smrg mgaReg->Option2, PCI_MGA_OPTION2); 1678fe5e51b7Smrg 1679fe5e51b7Smrg if (pMga->Chipset == PCI_CHIP_MGAG400 1680fe5e51b7Smrg || pMga->Chipset == PCI_CHIP_MGAG550) { 1681fe5e51b7Smrg pci_device_cfg_write_bits(pMga->PciInfo, OPTION3_MASK, 1682fe5e51b7Smrg mgaReg->Option3, 1683fe5e51b7Smrg PCI_MGA_OPTION3); 1684fe5e51b7Smrg } 1685fe5e51b7Smrg } 1686fe5e51b7Smrg#else 1687fe5e51b7Smrg /* restore pci_option register */ 1688fe5e51b7Smrg pciSetBitsLong(pMga->PciTag, PCI_OPTION_REG, optionMask, 1689fe5e51b7Smrg mgaReg->Option); 1690fe5e51b7Smrg if (pMga->Chipset != PCI_CHIP_MGA1064) 1691fe5e51b7Smrg pciSetBitsLong(pMga->PciTag, PCI_MGA_OPTION2, OPTION2_MASK, 1692fe5e51b7Smrg mgaReg->Option2); 1693fe5e51b7Smrg if (pMga->Chipset == PCI_CHIP_MGAG400 || pMga->Chipset == PCI_CHIP_MGAG550) 1694fe5e51b7Smrg pciSetBitsLong(pMga->PciTag, PCI_MGA_OPTION3, OPTION3_MASK, 1695fe5e51b7Smrg mgaReg->Option3); 1696fe5e51b7Smrg#endif 1697fe5e51b7Smrg } 1698eda3803bSmrg 16990bb88ba4Smrg if (pMga->is_G200ER) { 17000bb88ba4Smrg MGAG200ERPIXPLLSET(pScrn, mgaReg); 17010bb88ba4Smrg } else if (pMga->is_G200EV) { 1702eda3803bSmrg MGAG200EVPIXPLLSET(pScrn, mgaReg); 1703eda3803bSmrg } else if (pMga->is_G200WB) { 1704eda3803bSmrg MGAG200WBPIXPLLSET(pScrn, mgaReg); 1705a31a186aSmrg } else if (pMga->is_G200EH) { 1706a31a186aSmrg MGAG200EHPIXPLLSET(pScrn, mgaReg); 1707eda3803bSmrg } 1708fe5e51b7Smrg); /* MGA_NOT_HAL */ 1709fe5e51b7Smrg /* restore CRTCEXT regs */ 1710fe5e51b7Smrg for (i = 0; i < 6; i++) 1711fe5e51b7Smrg OUTREG16(MGAREG_CRTCEXT_INDEX, (mgaReg->ExtVga[i] << 8) | i); 1712fe5e51b7Smrg 17130bb88ba4Smrg if (pMga->is_G200ER) { 17140bb88ba4Smrg OUTREG8(MGAREG_CRTCEXT_INDEX, 0x24); 17156f68ce78Smrg OUTREG8(MGAREG_CRTCEXT_DATA, mgaReg->ExtVga_MgaReq); 17166f68ce78Smrg } 17176f68ce78Smrg 17186f68ce78Smrg if (pMga->is_G200WB) { 17196f68ce78Smrg if(pMga->Chipset == PCI_CHIP_MGAG200_EW3_PCI) 17206f68ce78Smrg { 17216f68ce78Smrg OUTREG8(MGAREG_CRTCEXT_INDEX, 0x34); 17226f68ce78Smrg OUTREG8(MGAREG_CRTCEXT_DATA, mgaReg->ExtVga_MgaReq); 17236f68ce78Smrg } 17240bb88ba4Smrg } 17250bb88ba4Smrg 1726fe5e51b7Smrg /* This handles restoring the generic VGA registers. */ 1727fe5e51b7Smrg if (pMga->is_G200SE) { 1728fe5e51b7Smrg MGAG200SERestoreMode(pScrn, vgaReg); 1729fe5e51b7Smrg if (restoreFonts) 1730fe5e51b7Smrg MGAG200SERestoreFonts(pScrn, vgaReg); 1731fe5e51b7Smrg } else { 1732fe5e51b7Smrg vgaHWRestore(pScrn, vgaReg, 1733fe5e51b7Smrg VGA_SR_MODE | (restoreFonts ? VGA_SR_FONTS : 0)); 1734fe5e51b7Smrg } 1735fe5e51b7Smrg MGAGRestorePalette(pScrn, vgaReg->DAC); 1736fe5e51b7Smrg 1737eda3803bSmrg 1738eda3803bSmrg if (pMga->is_G200EV) { 1739eda3803bSmrg OUTREG16(MGAREG_CRTCEXT_INDEX, 6); 1740eda3803bSmrg OUTREG16(MGAREG_CRTCEXT_DATA, 0); 1741eda3803bSmrg } 17420bb88ba4Smrg 1743fe5e51b7Smrg /* 1744fe5e51b7Smrg * this is needed to properly restore start address 1745fe5e51b7Smrg */ 1746fe5e51b7Smrg OUTREG16(MGAREG_CRTCEXT_INDEX, (mgaReg->ExtVga[0] << 8) | 0); 1747eda3803bSmrg 1748eda3803bSmrgMGA_NOT_HAL( 1749eda3803bSmrg if (pMga->is_G200WB) 1750eda3803bSmrg { 1751eda3803bSmrg MGAG200WBRestoreFromModeSwitch(pScrn); 1752eda3803bSmrg } 1753eda3803bSmrg); 1754eda3803bSmrg 1755fe5e51b7Smrg } else { 1756fe5e51b7Smrg /* Second Crtc */ 1757fe5e51b7Smrg xMODEINFO ModeInfo; 1758fe5e51b7Smrg 1759fe5e51b7SmrgMGA_NOT_HAL( 1760fe5e51b7Smrg /* Enable Dual Head */ 1761fe5e51b7Smrg MGACRTC2Set(pScrn, &ModeInfo); 1762fe5e51b7Smrg MGAEnableSecondOutPut(pScrn, &ModeInfo); 1763fe5e51b7Smrg MGACRTC2SetPitch(pScrn, &ModeInfo); 1764fe5e51b7Smrg MGACRTC2SetDisplayStart(pScrn, &ModeInfo,0,0,0); 1765fe5e51b7Smrg 1766fe5e51b7Smrg for (i = 0x80; i <= 0xa0; i ++) { 1767fe5e51b7Smrg if (i== 0x8d) { 1768fe5e51b7Smrg i = 0x8f; 1769fe5e51b7Smrg continue; 1770fe5e51b7Smrg } 1771fe5e51b7Smrg outMGAdac(i, mgaReg->dac2[ i - 0x80]); 1772fe5e51b7Smrg } 1773eda3803bSmrg 1774fe5e51b7Smrg); /* MGA_NOT_HAL */ 1775fe5e51b7Smrg 1776fe5e51b7Smrg } 1777fe5e51b7Smrg 1778fe5e51b7Smrg#ifdef DEBUG 1779fe5e51b7Smrg ErrorF("Setting DAC:"); 1780fe5e51b7Smrg for (i=0; i<DACREGSIZE; i++) { 1781fe5e51b7Smrg#if 1 1782fe5e51b7Smrg if(!(i%16)) ErrorF("\n%02X: ",i); 1783fe5e51b7Smrg ErrorF("%02X ", mgaReg->DacRegs[i]); 1784fe5e51b7Smrg#else 1785fe5e51b7Smrg if(!(i%8)) ErrorF("\n%02X: ",i); 1786fe5e51b7Smrg ErrorF("0x%02X, ", mgaReg->DacRegs[i]); 1787fe5e51b7Smrg#endif 1788fe5e51b7Smrg } 178981f79626Smrg ErrorF("\nOPTION = %08X\n", (unsigned)mgaReg->Option); 179081f79626Smrg ErrorF("OPTION2 = %08X\n", (unsigned)mgaReg->Option2); 1791fe5e51b7Smrg ErrorF("CRTCEXT:"); 1792fe5e51b7Smrg for (i=0; i<6; i++) ErrorF(" %02X", mgaReg->ExtVga[i]); 1793fe5e51b7Smrg ErrorF("\n"); 1794fe5e51b7Smrg#endif 1795fe5e51b7Smrg 1796fe5e51b7Smrg} 1797fe5e51b7Smrg 1798fe5e51b7Smrg/* 1799fe5e51b7Smrg * MGAGSave 1800fe5e51b7Smrg * 1801fe5e51b7Smrg * This function saves the video state. 1802fe5e51b7Smrg */ 1803fe5e51b7Smrgstatic void 1804fe5e51b7SmrgMGAGSave(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, MGARegPtr mgaReg, 1805fe5e51b7Smrg Bool saveFonts) 1806fe5e51b7Smrg{ 1807fe5e51b7Smrg int i; 1808fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1809fe5e51b7Smrg 1810fe5e51b7Smrg /* 1811fe5e51b7Smrg * Pixel Clock needs to be restored regardless if we use 1812fe5e51b7Smrg * HALLib or not. HALlib doesn't do a good job restoring 1813fe5e51b7Smrg * VESA modes (s.o.). MATROX: hint, hint. 1814fe5e51b7Smrg */ 1815fe5e51b7Smrg if (MGAISGx50(pMga)) { 1816493f84f4Smrg mgaReg->Pan_Ctl = inMGAdac(MGA1064_PAN_CTL); 1817fe5e51b7Smrg mgaReg->Clock = MGAG450SavePLLFreq(pScrn); 1818fe5e51b7Smrg } 1819fe5e51b7Smrg 1820fe5e51b7Smrg if(pMga->SecondCrtc == TRUE) { 1821fe5e51b7Smrg for(i = 0x80; i < 0xa0; i++) 1822fe5e51b7Smrg mgaReg->dac2[i-0x80] = inMGAdac(i); 1823fe5e51b7Smrg 1824fe5e51b7Smrg return; 1825fe5e51b7Smrg } 1826fe5e51b7Smrg 1827fe5e51b7Smrg MGA_NOT_HAL( 1828fe5e51b7Smrg /* Allocate the DacRegs space if not done already */ 1829fe5e51b7Smrg if (mgaReg->DacRegs == NULL) { 1830fe5e51b7Smrg mgaReg->DacRegs = xnfcalloc(DACREGSIZE, 1); 1831fe5e51b7Smrg } 1832fe5e51b7Smrg ); /* MGA_NOT_HAL */ 1833fe5e51b7Smrg 1834fe5e51b7Smrg /* 1835fe5e51b7Smrg * Code is needed to get back to bank zero. 1836fe5e51b7Smrg */ 1837fe5e51b7Smrg OUTREG16(MGAREG_CRTCEXT_INDEX, 0x0004); 1838fe5e51b7Smrg 1839fe5e51b7Smrg /* 1840fe5e51b7Smrg * This function will handle creating the data structure and filling 1841fe5e51b7Smrg * in the generic VGA portion. 1842fe5e51b7Smrg */ 1843fe5e51b7Smrg if (pMga->is_G200SE) { 1844fe5e51b7Smrg MGAG200SESaveMode(pScrn, vgaReg); 1845fe5e51b7Smrg if (saveFonts) 1846fe5e51b7Smrg MGAG200SESaveFonts(pScrn, vgaReg); 1847fe5e51b7Smrg } else { 1848fe5e51b7Smrg vgaHWSave(pScrn, vgaReg, VGA_SR_MODE | 1849fe5e51b7Smrg (saveFonts ? VGA_SR_FONTS : 0)); 1850fe5e51b7Smrg } 1851fe5e51b7Smrg MGAGSavePalette(pScrn, vgaReg->DAC); 1852fe5e51b7Smrg /* 1853fe5e51b7Smrg * Work around another bug in HALlib: it doesn't restore the 1854fe5e51b7Smrg * DAC width register correctly. 1855fe5e51b7Smrg */ 1856fe5e51b7Smrg 1857fe5e51b7Smrg MGA_NOT_HAL( 1858fe5e51b7Smrg /* 1859fe5e51b7Smrg * The port I/O code necessary to read in the extended registers. 1860fe5e51b7Smrg */ 1861fe5e51b7Smrg for (i = 0; i < DACREGSIZE; i++) 1862fe5e51b7Smrg mgaReg->DacRegs[i] = inMGAdac(i); 1863fe5e51b7Smrg 1864eda3803bSmrg if (pMga->is_G200WB) { 1865eda3803bSmrg mgaReg->PllM = inMGAdac(MGA1064_WB_PIX_PLLC_M); 1866eda3803bSmrg mgaReg->PllN = inMGAdac(MGA1064_WB_PIX_PLLC_N); 1867eda3803bSmrg mgaReg->PllP = inMGAdac(MGA1064_WB_PIX_PLLC_P); 1868eda3803bSmrg } else if (pMga->is_G200EV) { 1869eda3803bSmrg mgaReg->PllM = inMGAdac(MGA1064_EV_PIX_PLLC_M); 1870eda3803bSmrg mgaReg->PllN = inMGAdac(MGA1064_EV_PIX_PLLC_N); 1871eda3803bSmrg mgaReg->PllP = inMGAdac(MGA1064_EV_PIX_PLLC_P); 1872a31a186aSmrg } else if (pMga->is_G200EH) { 1873a31a186aSmrg mgaReg->PllM = inMGAdac(MGA1064_EH_PIX_PLLC_M); 1874a31a186aSmrg mgaReg->PllN = inMGAdac(MGA1064_EH_PIX_PLLC_N); 1875a31a186aSmrg mgaReg->PllP = inMGAdac(MGA1064_EH_PIX_PLLC_P); 18760bb88ba4Smrg } else if (pMga->is_G200ER) { 18770bb88ba4Smrg mgaReg->PllM = inMGAdac(MGA1064_ER_PIX_PLLC_M); 18780bb88ba4Smrg mgaReg->PllN = inMGAdac(MGA1064_ER_PIX_PLLC_N); 18790bb88ba4Smrg mgaReg->PllP = inMGAdac(MGA1064_ER_PIX_PLLC_P); 18800bb88ba4Smrg mgaReg->Dac_Index90 = inMGAdac(0x90); 1881eda3803bSmrg } 1882eda3803bSmrg 1883fe5e51b7Smrg mgaReg->PIXPLLCSaved = TRUE; 1884fe5e51b7Smrg 1885fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS 1886fe5e51b7Smrg pci_device_cfg_read_u32(pMga->PciInfo, & mgaReg->Option, 1887fe5e51b7Smrg PCI_OPTION_REG); 1888fe5e51b7Smrg pci_device_cfg_read_u32(pMga->PciInfo, & mgaReg->Option2, 1889fe5e51b7Smrg PCI_MGA_OPTION2); 1890fe5e51b7Smrg#else 1891fe5e51b7Smrg mgaReg->Option = pciReadLong(pMga->PciTag, PCI_OPTION_REG); 1892fe5e51b7Smrg 1893fe5e51b7Smrg mgaReg->Option2 = pciReadLong(pMga->PciTag, PCI_MGA_OPTION2); 1894fe5e51b7Smrg#endif 1895fe5e51b7Smrg if (pMga->Chipset == PCI_CHIP_MGAG400 || pMga->Chipset == PCI_CHIP_MGAG550) 1896fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS 1897fe5e51b7Smrg pci_device_cfg_read_u32(pMga->PciInfo, & mgaReg->Option3, 1898fe5e51b7Smrg PCI_MGA_OPTION3); 1899fe5e51b7Smrg#else 1900fe5e51b7Smrg mgaReg->Option3 = pciReadLong(pMga->PciTag, PCI_MGA_OPTION3); 1901fe5e51b7Smrg#endif 1902fe5e51b7Smrg ); /* MGA_NOT_HAL */ 1903fe5e51b7Smrg 1904fe5e51b7Smrg for (i = 0; i < 6; i++) 1905fe5e51b7Smrg { 1906fe5e51b7Smrg OUTREG8(MGAREG_CRTCEXT_INDEX, i); 1907fe5e51b7Smrg mgaReg->ExtVga[i] = INREG8(MGAREG_CRTCEXT_DATA); 1908fe5e51b7Smrg } 19090bb88ba4Smrg if (pMga->is_G200ER) 19100bb88ba4Smrg { 19110bb88ba4Smrg OUTREG8(MGAREG_CRTCEXT_INDEX, 0x24); 19126f68ce78Smrg mgaReg->ExtVga_MgaReq = INREG8(MGAREG_CRTCEXT_DATA); 19136f68ce78Smrg } 19146f68ce78Smrg if (pMga->is_G200WB) 19156f68ce78Smrg { 19166f68ce78Smrg if(pMga->Chipset == PCI_CHIP_MGAG200_EW3_PCI) 19176f68ce78Smrg { 19186f68ce78Smrg OUTREG8(MGAREG_CRTCEXT_INDEX, 0x34); 19196f68ce78Smrg mgaReg->ExtVga_MgaReq = INREG8(MGAREG_CRTCEXT_DATA); 19206f68ce78Smrg } 19216f68ce78Smrg } 1922fe5e51b7Smrg 1923fe5e51b7Smrg#ifdef DEBUG 1924fe5e51b7Smrg ErrorF("Saved values:\nDAC:"); 1925fe5e51b7Smrg for (i=0; i<DACREGSIZE; i++) { 1926fe5e51b7Smrg#if 1 1927fe5e51b7Smrg if(!(i%16)) ErrorF("\n%02X: ",i); 1928fe5e51b7Smrg ErrorF("%02X ", mgaReg->DacRegs[i]); 1929fe5e51b7Smrg#else 1930fe5e51b7Smrg if(!(i%8)) ErrorF("\n%02X: ",i); 1931fe5e51b7Smrg ErrorF("0x%02X, ", mgaReg->DacRegs[i]); 1932fe5e51b7Smrg#endif 1933fe5e51b7Smrg } 193481f79626Smrg ErrorF("\nOPTION = %08X\n:", (unsigned)mgaReg->Option); 193581f79626Smrg ErrorF("OPTION2 = %08X\nCRTCEXT:", (unsigned)mgaReg->Option2); 1936fe5e51b7Smrg for (i=0; i<6; i++) ErrorF(" %02X", mgaReg->ExtVga[i]); 1937fe5e51b7Smrg ErrorF("\n"); 1938fe5e51b7Smrg#endif 1939fe5e51b7Smrg} 1940fe5e51b7Smrg 1941fe5e51b7Smrg/**** 1942fe5e51b7Smrg *** HW Cursor 1943fe5e51b7Smrg */ 1944fe5e51b7Smrgstatic void 1945fe5e51b7SmrgMGAGLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src) 1946fe5e51b7Smrg{ 1947fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1948fe5e51b7Smrg CARD32 *dst = (CARD32*)(pMga->FbBase + pMga->FbCursorOffset); 1949fe5e51b7Smrg int i = 128; 1950fe5e51b7Smrg 1951fe5e51b7Smrg /* swap bytes in each line */ 1952fe5e51b7Smrg while( i-- ) { 1953fe5e51b7Smrg *dst++ = (src[4] << 24) | (src[5] << 16) | (src[6] << 8) | src[7]; 1954fe5e51b7Smrg *dst++ = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3]; 1955fe5e51b7Smrg src += 8; 1956fe5e51b7Smrg } 1957fe5e51b7Smrg} 1958fe5e51b7Smrg 1959fe5e51b7Smrgstatic void 1960fe5e51b7SmrgMGAGShowCursor(ScrnInfoPtr pScrn) 1961fe5e51b7Smrg{ 1962fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1963fe5e51b7Smrg /* Enable cursor - X-Windows mode */ 1964fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_CTL, 0x03); 1965fe5e51b7Smrg} 1966fe5e51b7Smrg 1967fe5e51b7Smrgstatic void 1968fe5e51b7SmrgMGAGShowCursorG100(ScrnInfoPtr pScrn) 1969fe5e51b7Smrg{ 1970fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1971fe5e51b7Smrg /* Enable cursor - X-Windows mode */ 1972fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_CTL, 0x01); 1973fe5e51b7Smrg} 1974fe5e51b7Smrg 1975fe5e51b7Smrgstatic void 1976fe5e51b7SmrgMGAGHideCursor(ScrnInfoPtr pScrn) 1977fe5e51b7Smrg{ 1978fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1979fe5e51b7Smrg /* Disable cursor */ 1980fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_CTL, 0x00); 1981fe5e51b7Smrg} 1982fe5e51b7Smrg 1983fe5e51b7Smrgstatic void 1984fe5e51b7SmrgMGAGSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) 1985fe5e51b7Smrg{ 1986fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1987fe5e51b7Smrg x += 64; 1988fe5e51b7Smrg y += 64; 1989fe5e51b7Smrg 1990fe5e51b7Smrg /* cursor update must never occurs during a retrace period (pp 4-160) */ 1991fe5e51b7Smrg while( INREG( MGAREG_Status ) & 0x08 ); 1992fe5e51b7Smrg 1993fe5e51b7Smrg /* Output position - "only" 12 bits of location documented */ 1994fe5e51b7Smrg OUTREG8( RAMDAC_OFFSET + MGA1064_CUR_XLOW, (x & 0xFF)); 1995fe5e51b7Smrg OUTREG8( RAMDAC_OFFSET + MGA1064_CUR_XHI, (x & 0xF00) >> 8); 1996fe5e51b7Smrg OUTREG8( RAMDAC_OFFSET + MGA1064_CUR_YLOW, (y & 0xFF)); 1997fe5e51b7Smrg OUTREG8( RAMDAC_OFFSET + MGA1064_CUR_YHI, (y & 0xF00) >> 8); 1998fe5e51b7Smrg} 1999fe5e51b7Smrg 2000fe5e51b7Smrg 2001fe5e51b7Smrgstatic void 2002fe5e51b7SmrgMGAGSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) 2003fe5e51b7Smrg{ 2004fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 2005fe5e51b7Smrg 2006fe5e51b7Smrg /* Background color */ 2007fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL0_RED, (bg & 0x00FF0000) >> 16); 2008fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL0_GREEN, (bg & 0x0000FF00) >> 8); 2009fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL0_BLUE, (bg & 0x000000FF)); 2010fe5e51b7Smrg 2011fe5e51b7Smrg /* Foreground color */ 2012fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL1_RED, (fg & 0x00FF0000) >> 16); 2013fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL1_GREEN, (fg & 0x0000FF00) >> 8); 2014fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL1_BLUE, (fg & 0x000000FF)); 2015fe5e51b7Smrg} 2016fe5e51b7Smrg 2017fe5e51b7Smrgstatic void 2018fe5e51b7SmrgMGAGSetCursorColorsG100(ScrnInfoPtr pScrn, int bg, int fg) 2019fe5e51b7Smrg{ 2020fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 2021fe5e51b7Smrg 2022fe5e51b7Smrg /* Background color */ 2023fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL1_RED, (bg & 0x00FF0000) >> 16); 2024fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL1_GREEN, (bg & 0x0000FF00) >> 8); 2025fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL1_BLUE, (bg & 0x000000FF)); 2026fe5e51b7Smrg 2027fe5e51b7Smrg /* Foreground color */ 2028fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL2_RED, (fg & 0x00FF0000) >> 16); 2029fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL2_GREEN, (fg & 0x0000FF00) >> 8); 2030fe5e51b7Smrg outMGAdac(MGA1064_CURSOR_COL2_BLUE, (fg & 0x000000FF)); 2031fe5e51b7Smrg} 2032fe5e51b7Smrg 2033fe5e51b7Smrgstatic Bool 2034fe5e51b7SmrgMGAGUseHWCursor(ScreenPtr pScrn, CursorPtr pCurs) 2035fe5e51b7Smrg{ 20360bb88ba4Smrg MGAPtr pMga = MGAPTR(xf86ScreenToScrn(pScrn)); 2037fe5e51b7Smrg /* This needs to detect if its on the second dac */ 2038fe5e51b7Smrg if( XF86SCRNINFO(pScrn)->currentMode->Flags & V_DBLSCAN ) 2039fe5e51b7Smrg return FALSE; 2040fe5e51b7Smrg if( pMga->SecondCrtc == TRUE ) 2041fe5e51b7Smrg return FALSE; 2042fe5e51b7Smrg return TRUE; 2043fe5e51b7Smrg} 2044fe5e51b7Smrg 2045fe5e51b7Smrg 2046fe5e51b7Smrg/* 2047fe5e51b7Smrg * According to mga-1064g.pdf pp215-216 (4-179 & 4-180) the low bits of 2048fe5e51b7Smrg * XGENIODATA and XGENIOCTL are connected to the 4 DDC pins, but don't say 2049fe5e51b7Smrg * which VGA line is connected to each DDC pin, so I've had to guess. 2050fe5e51b7Smrg * 2051fe5e51b7Smrg * DDC1 support only requires DDC_SDA_MASK, 2052fe5e51b7Smrg * DDC2 support requires DDC_SDA_MASK and DDC_SCL_MASK 2053fe5e51b7Smrg * 2054fe5e51b7Smrg * If we want DDC on second head (P2) then we must use DDC2 protocol (I2C) 2055fe5e51b7Smrg * 2056fe5e51b7Smrg * Be careful, DDC1 and DDC2 refer to protocols, DDC_P1 and DDC_P2 refer to 2057fe5e51b7Smrg * DDC data coming in on which videoport on the card 2058fe5e51b7Smrg */ 2059eda3803bSmrg#define DDC_P1_SDA_MASK (1 << 1) 2060eda3803bSmrg#define DDC_P1_SCL_MASK (1 << 3) 2061eda3803bSmrg 2062eda3803bSmrgstatic const struct mgag_i2c_private { 2063eda3803bSmrg unsigned sda_mask; 2064eda3803bSmrg unsigned scl_mask; 2065eda3803bSmrg} i2c_priv[] = { 2066eda3803bSmrg { (1 << 1), (1 << 3) }, 2067eda3803bSmrg { (1 << 0), (1 << 2) }, 2068eda3803bSmrg { (1 << 4), (1 << 5) }, 2069eda3803bSmrg { (1 << 0), (1 << 1) }, /* G200SE, G200EV and G200WB I2C bits */ 20700bb88ba4Smrg { (1 << 1), (1 << 0) }, /* G200EH, G200ER I2C bits */ 2071eda3803bSmrg}; 2072eda3803bSmrg 2073fe5e51b7Smrg 2074fe5e51b7Smrgstatic unsigned int 2075fe5e51b7SmrgMGAG_ddc1Read(ScrnInfoPtr pScrn) 2076fe5e51b7Smrg{ 2077fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 2078fe5e51b7Smrg unsigned char val; 2079eda3803bSmrg int i2c_index; 2080eda3803bSmrg 2081eda3803bSmrg if (pMga->is_G200SE || pMga->is_G200WB || pMga->is_G200EV) 2082eda3803bSmrg i2c_index = 3; 20830bb88ba4Smrg else if (pMga->is_G200EH || pMga->is_G200ER) 2084a31a186aSmrg i2c_index = 4; 2085eda3803bSmrg else 2086eda3803bSmrg i2c_index = 0; 2087eda3803bSmrg 2088eda3803bSmrg const struct mgag_i2c_private *p = & i2c_priv[i2c_index]; 2089eda3803bSmrg 2090fe5e51b7Smrg /* Define the SDA as an input */ 2091eda3803bSmrg outMGAdacmsk(MGA1064_GEN_IO_CTL, ~(p->scl_mask | p->sda_mask), 0); 2092fe5e51b7Smrg 2093fe5e51b7Smrg /* wait for Vsync */ 2094fe5e51b7Smrg if (pMga->is_G200SE) { 2095fe5e51b7Smrg usleep(4); 2096fe5e51b7Smrg } else { 2097fe5e51b7Smrg while( INREG( MGAREG_Status ) & 0x08 ); 2098fe5e51b7Smrg while( ! (INREG( MGAREG_Status ) & 0x08) ); 2099fe5e51b7Smrg } 2100fe5e51b7Smrg 2101fe5e51b7Smrg /* Get the result */ 2102eda3803bSmrg val = (inMGAdac(MGA1064_GEN_IO_DATA) & p->sda_mask); 2103fe5e51b7Smrg return val; 2104fe5e51b7Smrg} 2105fe5e51b7Smrg 2106fe5e51b7Smrgstatic void 2107eda3803bSmrgMGAG_I2CGetBits(I2CBusPtr b, int *clock, int *data) 2108fe5e51b7Smrg{ 2109fe5e51b7Smrg ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; 2110fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 2111eda3803bSmrg const struct mgag_i2c_private *p = 2112eda3803bSmrg (struct mgag_i2c_private *) b->DriverPrivate.ptr; 2113fe5e51b7Smrg unsigned char val; 2114fe5e51b7Smrg 2115fe5e51b7Smrg /* Get the result. */ 2116fe5e51b7Smrg val = inMGAdac(MGA1064_GEN_IO_DATA); 2117fe5e51b7Smrg 2118eda3803bSmrg *clock = (val & p->scl_mask) != 0; 2119eda3803bSmrg *data = (val & p->sda_mask) != 0; 2120fe5e51b7Smrg#ifdef DEBUG 2121fe5e51b7Smrg ErrorF("MGAG_I2CGetBits(%p,...) val=0x%x, returns clock %d, data %d\n", b, val, *clock, *data); 2122fe5e51b7Smrg#endif 2123fe5e51b7Smrg} 2124fe5e51b7Smrg 2125fe5e51b7Smrg/* 2126fe5e51b7Smrg * ATTENTION! - the DATA and CLOCK lines need to be tri-stated when 2127fe5e51b7Smrg * high. Therefore turn off output driver for the line to set line 2128fe5e51b7Smrg * to high. High signal is maintained by a 15k Ohm pull-up resistor. 2129fe5e51b7Smrg */ 2130fe5e51b7Smrgstatic void 2131eda3803bSmrgMGAG_I2CPutBits(I2CBusPtr b, int clock, int data) 2132fe5e51b7Smrg{ 2133fe5e51b7Smrg ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; 2134fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 2135eda3803bSmrg const struct mgag_i2c_private *p = 2136eda3803bSmrg (struct mgag_i2c_private *) b->DriverPrivate.ptr; 2137fe5e51b7Smrg unsigned char drv, val; 2138fe5e51b7Smrg 2139eda3803bSmrg val = (clock ? p->scl_mask : 0) | (data ? p->sda_mask : 0); 2140eda3803bSmrg drv = ((!clock) ? p->scl_mask : 0) | ((!data) ? p->sda_mask : 0); 2141fe5e51b7Smrg 2142fe5e51b7Smrg /* Write the values */ 2143eda3803bSmrg outMGAdacmsk(MGA1064_GEN_IO_CTL, ~(p->scl_mask | p->sda_mask) , drv); 2144eda3803bSmrg outMGAdacmsk(MGA1064_GEN_IO_DATA, ~(p->scl_mask | p->sda_mask) , val); 2145fe5e51b7Smrg#ifdef DEBUG 2146fe5e51b7Smrg ErrorF("MGAG_I2CPutBits(%p, %d, %d) val=0x%x\n", b, clock, data, val); 2147fe5e51b7Smrg#endif 2148fe5e51b7Smrg} 2149fe5e51b7Smrg 2150fe5e51b7Smrg 2151eda3803bSmrgstatic I2CBusPtr 215281f79626Smrgmgag_create_i2c_bus(char *name, unsigned bus_index, unsigned scrn_index) 2153fe5e51b7Smrg{ 2154eda3803bSmrg I2CBusPtr I2CPtr = xf86CreateI2CBusRec(); 2155eda3803bSmrg 2156eda3803bSmrg if (I2CPtr != NULL) { 2157eda3803bSmrg I2CPtr->BusName = name; 2158eda3803bSmrg I2CPtr->scrnIndex = scrn_index; 2159eda3803bSmrg I2CPtr->I2CPutBits = MGAG_I2CPutBits; 2160eda3803bSmrg I2CPtr->I2CGetBits = MGAG_I2CGetBits; 2161eda3803bSmrg I2CPtr->AcknTimeout = 5; 216281f79626Smrg I2CPtr->DriverPrivate.ptr = (void *) &i2c_priv[bus_index]; 2163eda3803bSmrg 2164eda3803bSmrg if (!xf86I2CBusInit(I2CPtr)) { 2165eda3803bSmrg xf86DestroyI2CBusRec(I2CPtr, TRUE, TRUE); 2166eda3803bSmrg I2CPtr = NULL; 2167eda3803bSmrg } 2168eda3803bSmrg } 2169eda3803bSmrg 2170eda3803bSmrg return I2CPtr; 2171fe5e51b7Smrg} 2172fe5e51b7Smrg 2173eda3803bSmrg 2174fe5e51b7SmrgBool 2175fe5e51b7SmrgMGAG_i2cInit(ScrnInfoPtr pScrn) 2176fe5e51b7Smrg{ 2177fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 2178fe5e51b7Smrg 2179fe5e51b7Smrg if (pMga->SecondCrtc == FALSE) { 2180eda3803bSmrg int i2c_index; 2181fe5e51b7Smrg 2182eda3803bSmrg if (pMga->is_G200SE || pMga->is_G200WB || pMga->is_G200EV) 2183eda3803bSmrg i2c_index = 3; 21840bb88ba4Smrg else if (pMga->is_G200EH || pMga->is_G200ER) 2185a31a186aSmrg i2c_index = 4; 2186eda3803bSmrg else 2187eda3803bSmrg i2c_index = 0; 2188fe5e51b7Smrg 2189eda3803bSmrg pMga->DDC_Bus1 = mgag_create_i2c_bus("DDC P1", 2190eda3803bSmrg i2c_index, pScrn->scrnIndex); 2191eda3803bSmrg return (pMga->DDC_Bus1 != NULL); 2192eda3803bSmrg } else { 2193eda3803bSmrg /* We have a dual head setup on G-series, set up DDC #2. */ 2194eda3803bSmrg pMga->DDC_Bus2 = mgag_create_i2c_bus("DDC P2", 1, pScrn->scrnIndex); 2195eda3803bSmrg 2196eda3803bSmrg if (pMga->DDC_Bus2 != NULL) { 2197eda3803bSmrg /* 0xA0 is DDC EEPROM address */ 2198eda3803bSmrg if (!xf86I2CProbeAddress(pMga->DDC_Bus2, 0xA0)) { 2199eda3803bSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "DDC #2 unavailable -> TV cable connected or no monitor connected!\n"); 2200eda3803bSmrg pMga->Crtc2IsTV = TRUE; /* assume for now. We need to fix HAL interactions. */ 2201fe5e51b7Smrg } 2202eda3803bSmrg } 2203fe5e51b7Smrg 2204fe5e51b7Smrg /* Then try to set up MAVEN bus. */ 2205eda3803bSmrg pMga->Maven_Bus = mgag_create_i2c_bus("MAVEN", 2, pScrn->scrnIndex); 2206eda3803bSmrg if (pMga->Maven_Bus != NULL) { 2207eda3803bSmrg pMga->Maven = NULL; 2208eda3803bSmrg pMga->Maven_Version = 0; 2209eda3803bSmrg 2210eda3803bSmrg /* Try to detect the MAVEN. */ 2211eda3803bSmrg if (xf86I2CProbeAddress(pMga->Maven_Bus, MAVEN_READ)) { 2212eda3803bSmrg I2CDevPtr dp = xf86CreateI2CDevRec(); 2213eda3803bSmrg if (dp) { 2214eda3803bSmrg I2CByte maven_ver; 2215eda3803bSmrg 2216eda3803bSmrg dp->DevName = "MGA-TVO"; 2217eda3803bSmrg dp->SlaveAddr = MAVEN_WRITE; 2218eda3803bSmrg dp->pI2CBus = pMga->Maven_Bus; 2219eda3803bSmrg if (!xf86I2CDevInit(dp)) { 2220eda3803bSmrg xf86DestroyI2CDevRec(dp, TRUE); 2221eda3803bSmrg } else { 2222eda3803bSmrg pMga->Maven = dp; 2223eda3803bSmrg if (MGAMavenRead(pScrn, 0xB2, &maven_ver)) { 2224eda3803bSmrg /* heuristic stolen from matroxfb */ 2225eda3803bSmrg pMga->Maven_Version = (maven_ver < 0x14) 2226eda3803bSmrg ? 'B' : 'C'; 2227eda3803bSmrg 2228eda3803bSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2229eda3803bSmrg "MAVEN revision MGA-TVO-%c detected (0x%x)\n", 2230eda3803bSmrg pMga->Maven_Version, maven_ver); 2231eda3803bSmrg } else { 2232eda3803bSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Failed to determine MAVEN hardware version!\n"); 2233fe5e51b7Smrg } 2234fe5e51b7Smrg } 2235eda3803bSmrg } 2236eda3803bSmrg } 2237fe5e51b7Smrg 2238eda3803bSmrg if (pMga->Maven == NULL) { 2239eda3803bSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2240eda3803bSmrg "Failed to register MGA-TVO I2C device!\n"); 2241fe5e51b7Smrg } 2242eda3803bSmrg } 2243fe5e51b7Smrg } 2244fe5e51b7Smrg 2245fe5e51b7Smrg return TRUE; 2246fe5e51b7Smrg} 2247fe5e51b7Smrg 2248fe5e51b7Smrg 2249fe5e51b7Smrg/* 2250fe5e51b7Smrg * MGAGRamdacInit 2251fe5e51b7Smrg * Handle broken G100 special. 2252fe5e51b7Smrg */ 2253fe5e51b7Smrgstatic void 2254fe5e51b7SmrgMGAGRamdacInit(ScrnInfoPtr pScrn) 2255fe5e51b7Smrg{ 2256fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 2257fe5e51b7Smrg MGARamdacPtr MGAdac = &pMga->Dac; 2258fe5e51b7Smrg 2259fe5e51b7Smrg MGAdac->isHwCursor = TRUE; 2260fe5e51b7Smrg MGAdac->CursorOffscreenMemSize = 1024; 2261fe5e51b7Smrg MGAdac->CursorMaxWidth = 64; 2262fe5e51b7Smrg MGAdac->CursorMaxHeight = 64; 2263fe5e51b7Smrg MGAdac->SetCursorPosition = MGAGSetCursorPosition; 2264fe5e51b7Smrg MGAdac->LoadCursorImage = MGAGLoadCursorImage; 2265fe5e51b7Smrg MGAdac->HideCursor = MGAGHideCursor; 2266fe5e51b7Smrg if ((pMga->Chipset == PCI_CHIP_MGAG100) 2267fe5e51b7Smrg || (pMga->Chipset == PCI_CHIP_MGAG100)) { 2268fe5e51b7Smrg MGAdac->SetCursorColors = MGAGSetCursorColorsG100; 2269fe5e51b7Smrg MGAdac->ShowCursor = MGAGShowCursorG100; 2270fe5e51b7Smrg } else { 2271fe5e51b7Smrg MGAdac->SetCursorColors = MGAGSetCursorColors; 2272fe5e51b7Smrg MGAdac->ShowCursor = MGAGShowCursor; 2273fe5e51b7Smrg } 2274fe5e51b7Smrg MGAdac->UseHWCursor = MGAGUseHWCursor; 2275fe5e51b7Smrg MGAdac->CursorFlags = 2276fe5e51b7Smrg#if X_BYTE_ORDER == X_LITTLE_ENDIAN 2277fe5e51b7Smrg HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | 2278fe5e51b7Smrg#endif 2279fe5e51b7Smrg HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 | 2280fe5e51b7Smrg HARDWARE_CURSOR_TRUECOLOR_AT_8BPP; 2281fe5e51b7Smrg 2282fe5e51b7Smrg MGAdac->LoadPalette = MGAGLoadPalette; 2283fe5e51b7Smrg MGAdac->RestorePalette = MGAGRestorePalette; 2284fe5e51b7Smrg 2285fe5e51b7Smrg 2286fe5e51b7Smrg MGAdac->maxPixelClock = pMga->bios.pixel.max_freq; 2287fe5e51b7Smrg MGAdac->ClockFrom = X_PROBED; 2288fe5e51b7Smrg 2289fe5e51b7Smrg /* Disable interleaving and set the rounding value */ 2290fe5e51b7Smrg pMga->Interleave = FALSE; 2291fe5e51b7Smrg 2292fe5e51b7Smrg pMga->Roundings[0] = 64; 2293fe5e51b7Smrg pMga->Roundings[1] = 32; 2294fe5e51b7Smrg pMga->Roundings[2] = 64; 2295fe5e51b7Smrg pMga->Roundings[3] = 32; 2296fe5e51b7Smrg 2297fe5e51b7Smrg /* Clear Fast bitblt flag */ 2298fe5e51b7Smrg pMga->HasFBitBlt = FALSE; 2299fe5e51b7Smrg} 2300fe5e51b7Smrg 2301fe5e51b7Smrgvoid MGAGSetupFuncs(ScrnInfoPtr pScrn) 2302fe5e51b7Smrg{ 2303fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 2304fe5e51b7Smrg 2305fe5e51b7Smrg pMga->PreInit = MGAGRamdacInit; 2306fe5e51b7Smrg pMga->Save = MGAGSave; 2307fe5e51b7Smrg pMga->Restore = MGAGRestore; 2308fe5e51b7Smrg pMga->ModeInit = MGAGInit; 23090bb88ba4Smrg if ((!pMga->is_G200WB) && (!pMga->is_G200ER)) { 2310a31a186aSmrg pMga->ddc1Read = MGAG_ddc1Read; 2311a31a186aSmrg /* vgaHWddc1SetSpeed will only work if the card is in VGA mode */ 2312a31a186aSmrg pMga->DDC1SetSpeed = vgaHWddc1SetSpeedWeak(); 2313a31a186aSmrg } else { 2314a31a186aSmrg pMga->ddc1Read = NULL; 2315a31a186aSmrg pMga->DDC1SetSpeed = NULL; 2316a31a186aSmrg } 2317fe5e51b7Smrg pMga->i2cInit = MGAG_i2cInit; 2318fe5e51b7Smrg} 2319fe5e51b7Smrg 2320