#include "colormapst.h"
#include "xf86.h"
#include "xf86_OSproc.h"
#include "xf86_ansic.h"
#include "xf86PciInfo.h"
#include "xf86Pci.h"
#include "mga_bios.h"
#include "mga_reg.h"
#include "mga.h"
#include "mga_macros.h"
#include "xf86DDC.h"
#define DACREGSIZE 0x50
#define OPTION1_MASK 0xFFFFFEFF
#define OPTION2_MASK 0xFFFFFFFF
#define OPTION3_MASK 0xFFFFFFFF
#define OPTION1_MASK_PRIMARY 0xFFFC0FF
static void MGAGRamdacInit(ScrnInfoPtr);
static void MGAGSave(ScrnInfoPtr, vgaRegPtr, MGARegPtr, Bool);
static void MGAGRestore(ScrnInfoPtr, vgaRegPtr, MGARegPtr, Bool);
static Bool MGAGInit(ScrnInfoPtr, DisplayModePtr);
static void MGAGLoadPalette(ScrnInfoPtr, int, int*, LOCO*, VisualPtr);
static Bool MGAG_i2cInit(ScrnInfoPtr pScrn);
#define MGA_MIN_VCO_FREQ 50000
#define MGA_MAX_VCO_FREQ 310000
static double
MGAGCalcClock ( ScrnInfoPtr pScrn, long f_out,
int *best_m, int *best_n, int *p, int *s )
{
MGAPtr pMga = MGAPTR(pScrn);
int m, n;
double f_pll, f_vco;
double m_err, calc_f;
double ref_freq;
int feed_div_min, feed_div_max;
int in_div_min, in_div_max;
int post_div_max;
switch( pMga->Chipset )
{
case PCI_CHIP_MGA1064:
ref_freq = 14318.18;
feed_div_min = 100;
feed_div_max = 127;
in_div_min = 1;
in_div_max = 31;
post_div_max = 7;
break;
case PCI_CHIP_MGAG400:
case PCI_CHIP_MGAG550:
ref_freq = 27050.5;
feed_div_min = 7;
feed_div_max = 127;
in_div_min = 1;
in_div_max = 31;
post_div_max = 7;
break;
case PCI_CHIP_MGAG100:
case PCI_CHIP_MGAG100_PCI:
case PCI_CHIP_MGAG200:
case PCI_CHIP_MGAG200_PCI:
default:
if (pMga->Bios2.PinID && (pMga->Bios2.VidCtrl & 0x20))
ref_freq = 14318.18;
else
ref_freq = 27050.5;
feed_div_min = 7;
feed_div_max = 127;
in_div_min = 1;
in_div_max = 6;
post_div_max = 7;
break;
}
if ( f_out < ( MGA_MIN_VCO_FREQ / 8))
f_out = MGA_MIN_VCO_FREQ / 8;
f_vco = ( double ) f_out;
for ( *p = 0; *p <= post_div_max && f_vco < MGA_MIN_VCO_FREQ;
*p = *p * 2 + 1, f_vco *= 2.0);
m_err = f_out;
for ( m = in_div_min ; m <= in_div_max ; m++ )
{
for ( n = feed_div_min; n <= feed_div_max; n++ )
{
calc_f = ref_freq * (n + 1) / (m + 1) ;
if ( abs(calc_f - f_vco) < m_err ) {
m_err = abs(calc_f - f_vco);
*best_m = m;
*best_n = n;
}
}
}
f_vco = ref_freq * (*best_n + 1) / (*best_m + 1);
if ( (50000.0 <= f_vco)
&& (f_vco < 100000.0) )
*s = 0;
if ( (100000.0 <= f_vco)
&& (f_vco < 140000.0) )
*s = 1;
if ( (140000.0 <= f_vco)
&& (f_vco < 180000.0) )
*s = 2;
if ( (180000.0 <= f_vco) )
*s = 3;
f_pll = f_vco / ( *p + 1 );
#ifdef DEBUG
ErrorF( "f_out_requ =%ld f_pll_real=%.1f f_vco=%.1f n=0x%x m=0x%x p=0x%x s=0x%x\n",
f_out, f_pll, f_vco, *best_n, *best_m, *p, *s );
#endif
return f_pll;
}
static void
MGAGSetPCLK( ScrnInfoPtr pScrn, long f_out )
{
MGAPtr pMga = MGAPTR(pScrn);
MGARegPtr pReg = &pMga->ModeReg;
int m, n, p, s;
if(MGAISGx50(pMga)) {
pReg->Clock = f_out;
return;
}
(void) MGAGCalcClock( pScrn, f_out, &m, &n, &p, &s );
pReg->DacRegs[ MGA1064_PIX_PLLC_M ] = m & 0x1F;
pReg->DacRegs[ MGA1064_PIX_PLLC_N ] = n & 0x7F;
pReg->DacRegs[ MGA1064_PIX_PLLC_P ] = (p & 0x07) | ((s & 0x03) << 3);
}
static Bool
MGAGInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
{
const static unsigned char initDAC[] = {
0, 0, 0, 0, 0, 0, 0x00, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0x00, 0, 0xC9, 0xFF, 0xBF, 0x20, 0x1F, 0x20,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0, 0, 0, 0x40,
0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83,
0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
int i;
int hd, hs, he, ht, vd, vs, ve, vt, wd;
int BppShift;
MGAPtr pMga;
MGARegPtr pReg;
vgaRegPtr pVga;
MGAFBLayout *pLayout;
xMODEINFO ModeInfo;
ModeInfo.ulDispWidth = mode->HDisplay;
ModeInfo.ulDispHeight = mode->VDisplay;
ModeInfo.ulFBPitch = mode->HDisplay;
ModeInfo.ulBpp = pScrn->bitsPerPixel;
ModeInfo.flSignalMode = 0;
ModeInfo.ulPixClock = mode->Clock;
ModeInfo.ulHFPorch = mode->HSyncStart - mode->HDisplay;
ModeInfo.ulHSync = mode->HSyncEnd - mode->HSyncStart;
ModeInfo.ulHBPorch = mode->HTotal - mode->HSyncEnd;
ModeInfo.ulVFPorch = mode->VSyncStart - mode->VDisplay;
ModeInfo.ulVSync = mode->VSyncEnd - mode->VSyncStart;
ModeInfo.ulVBPorch = mode->VTotal - mode->VSyncEnd;
pMga = MGAPTR(pScrn);
pReg = &pMga->ModeReg;
pVga = &VGAHWPTR(pScrn)->ModeReg;
pLayout = &pMga->CurrentLayout;
BppShift = pMga->BppShifts[(pLayout->bitsPerPixel >> 3) - 1];
MGA_NOT_HAL(
if (pReg->DacRegs == NULL) {
pReg->DacRegs = xnfcalloc(DACREGSIZE, 1);
}
for (i = 0; i < DACREGSIZE; i++) {
pReg->DacRegs[i] = initDAC[i];
}
);
switch(pMga->Chipset)
{
case PCI_CHIP_MGA1064:
pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x04;
pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x44;
pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18;
pReg->Option = 0x5F094F21;
pReg->Option2 = 0x00000000;
break;
case PCI_CHIP_MGAG100:
case PCI_CHIP_MGAG100_PCI:
pReg->DacRegs[ MGAGDAC_XVREFCTRL ] = 0x03;
if(pMga->HasSDRAM) {
if(pMga->OverclockMem) {
pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x06;
pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x38;
pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18;
} else {
pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x01;
pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x0E;
pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18;
}
pReg->Option = 0x404991a9;
} else {
if(pMga->OverclockMem) {
pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x06;
pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x24;
pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x10;
} else {
pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x04;
pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x16;
pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x08;
}
pReg->Option = 0x4049d121;
}
pReg->Option2 = 0x0000007;
break;
case PCI_CHIP_MGAG400:
case PCI_CHIP_MGAG550:
#ifdef USEMGAHAL
MGA_HAL(break;);
#endif
if (MGAISGx50(pMga))
break;
if(pMga->Dac.maxPixelClock == 360000) {
if(pMga->OverclockMem) {
pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x05;
pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x42;
pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18;
pReg->Option3 = 0x019B8419;
pReg->Option = 0x50574120;
} else {
pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x02;
pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x1B;
pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18;
pReg->Option3 = 0x019B8419;
pReg->Option = 0x5053C120;
}
} else {
if(pMga->OverclockMem) {
pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x02;
pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x1B;
pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18;
pReg->Option3 = 0x019B8419;
pReg->Option = 0x5053C120;
} else {
pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x13;
pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x7A;
pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x08;
pReg->Option3 = 0x0190a421;
pReg->Option = 0x50044120;
}
}
if(pMga->HasSDRAM)
pReg->Option &= ~(1 << 14);
pReg->Option2 = 0x01003000;
break;
case PCI_CHIP_MGAG200:
case PCI_CHIP_MGAG200_PCI:
default:
#ifdef USEMGAHAL
MGA_HAL(break;);
#endif
if(pMga->OverclockMem) {
pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x06;
pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x24;
pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x10;
} else {
pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x04;
pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x2D;
pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x19;
}
pReg->Option2 = 0x00008000;
if(pMga->HasSDRAM)
pReg->Option = 0x40499121;
else
pReg->Option = 0x4049cd21;
break;
}
MGA_NOT_HAL(
pReg->Option &= ~0x20000000;
switch(pLayout->bitsPerPixel)
{
case 8:
pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_8bits;
break;
case 16:
pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_16bits;
if ( (pLayout->weight.red == 5) && (pLayout->weight.green == 5)
&& (pLayout->weight.blue == 5) ) {
pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_15bits;
}
break;
case 24:
pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_24bits;
break;
case 32:
if(pLayout->Overlay8Plus24) {
pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_32bits;
pReg->DacRegs[ MGA1064_COL_KEY_MSK_LSB ] = 0xFF;
pReg->DacRegs[ MGA1064_COL_KEY_LSB ] = pMga->colorKey;
} else
pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_32_24bits;
break;
default:
FatalError("MGA: unsupported depth\n");
}
);
if (!vgaHWInit(pScrn, mode))
return(FALSE);
hd = (mode->CrtcHDisplay >> 3) - 1;
hs = (mode->CrtcHSyncStart >> 3) - 1;
he = (mode->CrtcHSyncEnd >> 3) - 1;
ht = (mode->CrtcHTotal >> 3) - 1;
vd = mode->CrtcVDisplay - 1;
vs = mode->CrtcVSyncStart - 1;
ve = mode->CrtcVSyncEnd - 1;
vt = mode->CrtcVTotal - 2;
if((ht & 0x07) == 0x06 || (ht & 0x07) == 0x04)
ht++;
if (pLayout->bitsPerPixel == 24)
wd = (pLayout->displayWidth * 3) >> (4 - BppShift);
else
wd = pLayout->displayWidth >> (4 - BppShift);
pReg->ExtVga[0] = 0;
pReg->ExtVga[5] = 0;
if (mode->Flags & V_INTERLACE)
{
pReg->ExtVga[0] = 0x80;
pReg->ExtVga[5] = (hs + he - ht) >> 1;
wd <<= 1;
vt &= 0xFFFE;
}
pReg->ExtVga[0] |= (wd & 0x300) >> 4;
pReg->ExtVga[1] = (((ht - 4) & 0x100) >> 8) |
((hd & 0x100) >> 7) |
((hs & 0x100) >> 6) |
(ht & 0x40);
pReg->ExtVga[2] = ((vt & 0xc00) >> 10) |
((vd & 0x400) >> 8) |
((vd & 0xc00) >> 7) |
((vs & 0xc00) >> 5) |
((vd & 0x400) >> 3);
if (pLayout->bitsPerPixel == 24)
pReg->ExtVga[3] = (((1 << BppShift) * 3) - 1) | 0x80;
else
pReg->ExtVga[3] = ((1 << BppShift) - 1) | 0x80;
pReg->ExtVga[4] = 0;
pVga->CRTC[0] = ht - 4;
pVga->CRTC[1] = hd;
pVga->CRTC[2] = hd;
pVga->CRTC[3] = (ht & 0x1F) | 0x80;
pVga->CRTC[4] = hs;
pVga->CRTC[5] = ((ht & 0x20) << 2) | (he & 0x1F);
pVga->CRTC[6] = vt & 0xFF;
pVga->CRTC[7] = ((vt & 0x100) >> 8 ) |
((vd & 0x100) >> 7 ) |
((vs & 0x100) >> 6 ) |
((vd & 0x100) >> 5 ) |
((vd & 0x100) >> 4 ) |
((vt & 0x200) >> 4 ) |
((vd & 0x200) >> 3 ) |
((vs & 0x200) >> 2 );
pVga->CRTC[9] = ((vd & 0x200) >> 4) |
((vd & 0x200) >> 3);
pVga->CRTC[16] = vs & 0xFF;
pVga->CRTC[17] = (ve & 0x0F) | 0x20;
pVga->CRTC[18] = vd & 0xFF;
pVga->CRTC[19] = wd & 0xFF;
pVga->CRTC[21] = vd & 0xFF;
pVga->CRTC[22] = (vt + 1) & 0xFF;
pVga->CRTC[24] = vd & 0xFF;
MGA_NOT_HAL(pReg->DacRegs[MGA1064_CURSOR_BASE_ADR_LOW] = pMga->FbCursorOffset >> 10);
MGA_NOT_HAL(pReg->DacRegs[MGA1064_CURSOR_BASE_ADR_HI] = pMga->FbCursorOffset >> 18);
if (pMga->SyncOnGreen) {
MGA_NOT_HAL(pReg->DacRegs[MGA1064_GEN_CTL] &= ~0x20);
pReg->ExtVga[3] |= 0x40;
}
pVga->MiscOutReg |= 0x0C;
MGA_NOT_HAL(
if (mode->Flags & V_DBLSCAN)
pVga->CRTC[9] |= 0x80;
if(MGAISGx50(pMga)) {
OUTREG(MGAREG_ZORG, 0);
}
MGAGSetPCLK(pScrn, mode->Clock);
);
pVga->MiscOutReg &= ~0x02;
if (pMga->SecondCrtc)
{
MGACRTC2Get(pScrn, &ModeInfo);
MGACRTC2GetPitch(pScrn, &ModeInfo);
MGACRTC2GetDisplayStart(pScrn, &ModeInfo,0,0,0);
}
#if X_BYTE_ORDER == X_BIG_ENDIAN
pReg->Option &= ~0x80000000;
#endif
return(TRUE);
}
static void
MGAPaletteLoadCallback(ScrnInfoPtr pScrn)
{
MGAPtr pMga = MGAPTR(pScrn);
MGAPaletteInfo *pal = pMga->palinfo;
int i;
while (!(INREG8(0x1FDA) & 0x08));
for(i = 0; i < 256; i++) {
if(pal->update) {
outMGAdreg(MGA1064_WADR_PAL, i);
outMGAdreg(MGA1064_COL_PAL, pal->red);
outMGAdreg(MGA1064_COL_PAL, pal->green);
outMGAdreg(MGA1064_COL_PAL, pal->blue);
pal->update = FALSE;
}
pal++;
}
pMga->PaletteLoadCallback = NULL;
}
void MGAGLoadPalette(
ScrnInfoPtr pScrn,
int numColors,
int *indices,
LOCO *colors,
VisualPtr pVisual
){
MGAPtr pMga = MGAPTR(pScrn);
if((pMga->CurrentLayout.Overlay8Plus24) && (pVisual->nplanes != 8))
return;
if(pMga->Chipset == PCI_CHIP_MGAG400 || pMga->Chipset == PCI_CHIP_MGAG550){
while(numColors--) {
pMga->palinfo[*indices].update = TRUE;
pMga->palinfo[*indices].red = colors[*indices].red;
pMga->palinfo[*indices].green = colors[*indices].green;
pMga->palinfo[*indices].blue = colors[*indices].blue;
indices++;
}
pMga->PaletteLoadCallback = MGAPaletteLoadCallback;
return;
} else {
while(numColors--) {
outMGAdreg(MGA1064_WADR_PAL, *indices);
outMGAdreg(MGA1064_COL_PAL, colors[*indices].red);
outMGAdreg(MGA1064_COL_PAL, colors[*indices].green);
outMGAdreg(MGA1064_COL_PAL, colors[*indices].blue);
indices++;
}
}
}
static void
MGAGRestorePalette(ScrnInfoPtr pScrn, unsigned char* pntr)
{
MGAPtr pMga = MGAPTR(pScrn);
int i = 768;
outMGAdreg(MGA1064_WADR_PAL, 0x00);
while(i--)
outMGAdreg(MGA1064_COL_PAL, *(pntr++));
}
static void
MGAGSavePalette(ScrnInfoPtr pScrn, unsigned char* pntr)
{
MGAPtr pMga = MGAPTR(pScrn);
int i = 768;
outMGAdreg(MGA1064_RADR_PAL, 0x00);
while(i--)
*(pntr++) = inMGAdreg(MGA1064_COL_PAL);
}
static void
MGAGRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, MGARegPtr mgaReg,
Bool restoreFonts)
{
int i;
MGAPtr pMga = MGAPTR(pScrn);
CARD32 optionMask;
if (MGAISGx50(pMga) && mgaReg->Clock) {
MGAG450SetPLLFreq(pScrn, mgaReg->Clock);
mgaReg->PIXPLLCSaved = FALSE;
}
if(!pMga->SecondCrtc) {
#if X_BYTE_ORDER == X_BIG_ENDIAN
optionMask = OPTION1_MASK;
#else
optionMask = (pMga->Primary) ? OPTION1_MASK_PRIMARY : OPTION1_MASK;
#endif
MGA_NOT_HAL(
for (i = 0; i < DACREGSIZE; i++) {
if( (i <= 0x03) ||
(i == 0x07) ||
(i == 0x0b) ||
(i == 0x0f) ||
((i >= 0x13) && (i <= 0x17)) ||
(i == 0x1b) ||
(i == 0x1c) ||
((i >= 0x1f) && (i <= 0x29)) ||
((i >= 0x30) && (i <= 0x37)) ||
(MGAISGx50(pMga) && !mgaReg->PIXPLLCSaved &&
((i == 0x2c) || (i == 0x2d) || (i == 0x2e) ||
(i == 0x4c) || (i == 0x4d) || (i == 0x4e))))
continue;
outMGAdac(i, mgaReg->DacRegs[i]);
}
if (!MGAISGx50(pMga)) {
pciSetBitsLong(pMga->PciTag, PCI_OPTION_REG, optionMask,
mgaReg->Option);
if (pMga->Chipset != PCI_CHIP_MGA1064)
pciSetBitsLong(pMga->PciTag, PCI_MGA_OPTION2, OPTION2_MASK,
mgaReg->Option2);
if (pMga->Chipset == PCI_CHIP_MGAG400 || pMga->Chipset == PCI_CHIP_MGAG550)
pciSetBitsLong(pMga->PciTag, PCI_MGA_OPTION3, OPTION3_MASK,
mgaReg->Option3);
}
);
#ifdef USEMGAHAL
MGA_HAL(
outMGAdac(MGA1064_MUL_CTL,mgaReg->DacRegs[0]);
outMGAdac(MGA1064_MISC_CTL,mgaReg->DacRegs[1]);
if (!MGAISGx50(pMga)) {
outMGAdac(MGA1064_PIX_PLLC_M,mgaReg->DacRegs[2]);
outMGAdac(MGA1064_PIX_PLLC_N,mgaReg->DacRegs[3]);
outMGAdac(MGA1064_PIX_PLLC_P,mgaReg->DacRegs[4]);
}
);
#endif
for (i = 0; i < 6; i++)
OUTREG16(0x1FDE, (mgaReg->ExtVga[i] << 8) | i);
vgaHWRestore(pScrn, vgaReg,
VGA_SR_MODE | (restoreFonts ? VGA_SR_FONTS : 0));
MGAGRestorePalette(pScrn, vgaReg->DAC);
OUTREG16(0x1FDE, (mgaReg->ExtVga[0] << 8) | 0);
} else {
xMODEINFO ModeInfo;
MGA_NOT_HAL(
MGACRTC2Set(pScrn, &ModeInfo);
MGAEnableSecondOutPut(pScrn, &ModeInfo);
MGACRTC2SetPitch(pScrn, &ModeInfo);
MGACRTC2SetDisplayStart(pScrn, &ModeInfo,0,0,0);
for (i = 0x80; i <= 0xa0; i ++) {
if (i== 0x8d) {
i = 0x8f;
continue;
}
outMGAdac(i, mgaReg->dac2[ i - 0x80]);
}
);
}
#ifdef DEBUG
ErrorF("Setting DAC:");
for (i=0; i<DACREGSIZE; i++) {
#if 1
if(!(i%16)) ErrorF("\n%02X: ",i);
ErrorF("%02X ", mgaReg->DacRegs[i]);
#else
if(!(i%8)) ErrorF("\n%02X: ",i);
ErrorF("0x%02X, ", mgaReg->DacRegs[i]);
#endif
}
ErrorF("\nOPTION = %08lX\n", mgaReg->Option);
ErrorF("OPTION2 = %08lX\n", mgaReg->Option2);
ErrorF("CRTCEXT:");
for (i=0; i<6; i++) ErrorF(" %02X", mgaReg->ExtVga[i]);
ErrorF("\n");
#endif
}
static void
MGAGSave(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, MGARegPtr mgaReg,
Bool saveFonts)
{
int i;
MGAPtr pMga = MGAPTR(pScrn);
if (MGAISGx50(pMga)) {
mgaReg->Clock = MGAG450SavePLLFreq(pScrn);
}
if(pMga->SecondCrtc == TRUE) {
for(i = 0x80; i < 0xa0; i++)
mgaReg->dac2[i-0x80] = inMGAdac(i);
return;
}
MGA_NOT_HAL(
if (mgaReg->DacRegs == NULL) {
mgaReg->DacRegs = xnfcalloc(DACREGSIZE, 1);
}
);
OUTREG16(0x1FDE, 0x0004);
vgaHWSave(pScrn, vgaReg, VGA_SR_MODE | (saveFonts ? VGA_SR_FONTS : 0));
MGAGSavePalette(pScrn, vgaReg->DAC);
#ifdef USEMGAHAL
MGA_HAL(
if (mgaReg->DacRegs == NULL) {
mgaReg->DacRegs = xnfcalloc(MGAISGx50(pMga) ? 2 : 5, 1);
}
mgaReg->DacRegs[0] = inMGAdac(MGA1064_MUL_CTL);
mgaReg->DacRegs[1] = inMGAdac(MGA1064_MISC_CTL);
if (!MGAISGx50(pMga)) {
mgaReg->DacRegs[2] = inMGAdac(MGA1064_PIX_PLLC_M);
mgaReg->DacRegs[3] = inMGAdac(MGA1064_PIX_PLLC_N);
mgaReg->DacRegs[4] = inMGAdac(MGA1064_PIX_PLLC_P);
}
);
#endif
MGA_NOT_HAL(
for (i = 0; i < DACREGSIZE; i++)
mgaReg->DacRegs[i] = inMGAdac(i);
mgaReg->PIXPLLCSaved = TRUE;
mgaReg->Option = pciReadLong(pMga->PciTag, PCI_OPTION_REG);
mgaReg->Option2 = pciReadLong(pMga->PciTag, PCI_MGA_OPTION2);
if (pMga->Chipset == PCI_CHIP_MGAG400 || pMga->Chipset == PCI_CHIP_MGAG550)
mgaReg->Option3 = pciReadLong(pMga->PciTag, PCI_MGA_OPTION3);
);
for (i = 0; i < 6; i++)
{
OUTREG8(0x1FDE, i);
mgaReg->ExtVga[i] = INREG8(0x1FDF);
}
#ifdef DEBUG
ErrorF("Saved values:\nDAC:");
for (i=0; i<DACREGSIZE; i++) {
#if 1
if(!(i%16)) ErrorF("\n%02X: ",i);
ErrorF("%02X ", mgaReg->DacRegs[i]);
#else
if(!(i%8)) ErrorF("\n%02X: ",i);
ErrorF("0x%02X, ", mgaReg->DacRegs[i]);
#endif
}
ErrorF("\nOPTION = %08lX\n:", mgaReg->Option);
ErrorF("OPTION2 = %08lX\nCRTCEXT:", mgaReg->Option2);
for (i=0; i<6; i++) ErrorF(" %02X", mgaReg->ExtVga[i]);
ErrorF("\n");
#endif
}
static void
MGAGLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
{
MGAPtr pMga = MGAPTR(pScrn);
CARD32 *dst = (CARD32*)(pMga->FbBase + pMga->FbCursorOffset);
int i = 128;
while( i-- ) {
*dst++ = (src[4] << 24) | (src[5] << 16) | (src[6] << 8) | src[7];
*dst++ = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
src += 8;
}
}
static void
MGAGShowCursor(ScrnInfoPtr pScrn)
{
MGAPtr pMga = MGAPTR(pScrn);
outMGAdac(MGA1064_CURSOR_CTL, 0x03);
}
static void
MGAGShowCursorG100(ScrnInfoPtr pScrn)
{
MGAPtr pMga = MGAPTR(pScrn);
outMGAdac(MGA1064_CURSOR_CTL, 0x01);
}
static void
MGAGHideCursor(ScrnInfoPtr pScrn)
{
MGAPtr pMga = MGAPTR(pScrn);
outMGAdac(MGA1064_CURSOR_CTL, 0x00);
}
static void
MGAGSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
{
MGAPtr pMga = MGAPTR(pScrn);
x += 64;
y += 64;
#ifdef USEMGAHAL
MGA_HAL(
x += pMga->HALGranularityOffX;
y += pMga->HALGranularityOffY;
);
#endif
while( INREG( MGAREG_Status ) & 0x08 );
OUTREG8( RAMDAC_OFFSET + MGA1064_CUR_XLOW, (x & 0xFF));
OUTREG8( RAMDAC_OFFSET + MGA1064_CUR_XHI, (x & 0xF00) >> 8);
OUTREG8( RAMDAC_OFFSET + MGA1064_CUR_YLOW, (y & 0xFF));
OUTREG8( RAMDAC_OFFSET + MGA1064_CUR_YHI, (y & 0xF00) >> 8);
}
static void
MGAGSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
{
MGAPtr pMga = MGAPTR(pScrn);
outMGAdac(MGA1064_CURSOR_COL0_RED, (bg & 0x00FF0000) >> 16);
outMGAdac(MGA1064_CURSOR_COL0_GREEN, (bg & 0x0000FF00) >> 8);
outMGAdac(MGA1064_CURSOR_COL0_BLUE, (bg & 0x000000FF));
outMGAdac(MGA1064_CURSOR_COL1_RED, (fg & 0x00FF0000) >> 16);
outMGAdac(MGA1064_CURSOR_COL1_GREEN, (fg & 0x0000FF00) >> 8);
outMGAdac(MGA1064_CURSOR_COL1_BLUE, (fg & 0x000000FF));
}
static void
MGAGSetCursorColorsG100(ScrnInfoPtr pScrn, int bg, int fg)
{
MGAPtr pMga = MGAPTR(pScrn);
outMGAdac(MGA1064_CURSOR_COL1_RED, (bg & 0x00FF0000) >> 16);
outMGAdac(MGA1064_CURSOR_COL1_GREEN, (bg & 0x0000FF00) >> 8);
outMGAdac(MGA1064_CURSOR_COL1_BLUE, (bg & 0x000000FF));
outMGAdac(MGA1064_CURSOR_COL2_RED, (fg & 0x00FF0000) >> 16);
outMGAdac(MGA1064_CURSOR_COL2_GREEN, (fg & 0x0000FF00) >> 8);
outMGAdac(MGA1064_CURSOR_COL2_BLUE, (fg & 0x000000FF));
}
static Bool
MGAGUseHWCursor(ScreenPtr pScrn, CursorPtr pCurs)
{
MGAPtr pMga = MGAPTR(xf86Screens[pScrn->myNum]);
if( XF86SCRNINFO(pScrn)->currentMode->Flags & V_DBLSCAN )
return FALSE;
if( pMga->SecondCrtc == TRUE )
return FALSE;
return TRUE;
}
static const int DDC_SDA_MASK = 1 << 1;
static const int DDC_SCL_MASK = 1 << 3;
static unsigned int
MGAG_ddc1Read(ScrnInfoPtr pScrn)
{
MGAPtr pMga = MGAPTR(pScrn);
unsigned char val;
outMGAdacmsk(MGA1064_GEN_IO_CTL, ~(DDC_SCL_MASK | DDC_SDA_MASK), 0);
while( INREG( MGAREG_Status ) & 0x08 );
while( ! (INREG( MGAREG_Status ) & 0x08) );
val = (inMGAdac(MGA1064_GEN_IO_DATA) & DDC_SDA_MASK);
return val;
}
static void
MGAG_I2CGetBits(I2CBusPtr b, int *clock, int *data)
{
ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
MGAPtr pMga = MGAPTR(pScrn);
unsigned char val;
val = inMGAdac(MGA1064_GEN_IO_DATA);
*clock = (val & DDC_SCL_MASK) != 0;
*data = (val & DDC_SDA_MASK) != 0;
#ifdef DEBUG
ErrorF("MGAG_I2CGetBits(%p,...) val=0x%x, returns clock %d, data %d\n", b, val, *clock, *data);
#endif
}
static void
MGAG_I2CPutBits(I2CBusPtr b, int clock, int data)
{
ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
MGAPtr pMga = MGAPTR(pScrn);
unsigned char drv, val;
val = (clock ? DDC_SCL_MASK : 0) | (data ? DDC_SDA_MASK : 0);
drv = ((!clock) ? DDC_SCL_MASK : 0) | ((!data) ? DDC_SDA_MASK : 0);
outMGAdacmsk(MGA1064_GEN_IO_CTL, ~(DDC_SCL_MASK | DDC_SDA_MASK) , drv);
outMGAdacmsk(MGA1064_GEN_IO_DATA, ~(DDC_SCL_MASK | DDC_SDA_MASK) , val);
#ifdef DEBUG
ErrorF("MGAG_I2CPutBits(%p, %d, %d) val=0x%x\n", b, clock, data, val);
#endif
}
Bool
MGAG_i2cInit(ScrnInfoPtr pScrn)
{
MGAPtr pMga = MGAPTR(pScrn);
I2CBusPtr I2CPtr;
I2CPtr = xf86CreateI2CBusRec();
if(!I2CPtr) return FALSE;
pMga->I2C = I2CPtr;
I2CPtr->BusName = "DDC";
I2CPtr->scrnIndex = pScrn->scrnIndex;
I2CPtr->I2CPutBits = MGAG_I2CPutBits;
I2CPtr->I2CGetBits = MGAG_I2CGetBits;
I2CPtr->AcknTimeout = 5;
if (!xf86I2CBusInit(I2CPtr)) {
return FALSE;
}
return TRUE;
}
static void
MGAGRamdacInit(ScrnInfoPtr pScrn)
{
MGAPtr pMga = MGAPTR(pScrn);
MGARamdacPtr MGAdac = &pMga->Dac;
MGAdac->isHwCursor = TRUE;
MGAdac->CursorOffscreenMemSize = 1024;
MGAdac->CursorMaxWidth = 64;
MGAdac->CursorMaxHeight = 64;
MGAdac->SetCursorPosition = MGAGSetCursorPosition;
MGAdac->LoadCursorImage = MGAGLoadCursorImage;
MGAdac->HideCursor = MGAGHideCursor;
if ((pMga->Chipset == PCI_CHIP_MGAG100)
|| (pMga->Chipset == PCI_CHIP_MGAG100)) {
MGAdac->SetCursorColors = MGAGSetCursorColorsG100;
MGAdac->ShowCursor = MGAGShowCursorG100;
} else {
MGAdac->SetCursorColors = MGAGSetCursorColors;
MGAdac->ShowCursor = MGAGShowCursor;
}
MGAdac->UseHWCursor = MGAGUseHWCursor;
MGAdac->CursorFlags =
#if X_BYTE_ORDER == X_LITTLE_ENDIAN
HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
#endif
HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 |
HARDWARE_CURSOR_TRUECOLOR_AT_8BPP;
MGAdac->LoadPalette = MGAGLoadPalette;
MGAdac->RestorePalette = MGAGRestorePalette;
if ( pMga->Bios2.PinID && pMga->Bios2.PclkMax != 0xFF )
{
MGAdac->maxPixelClock = (pMga->Bios2.PclkMax + 100) * 1000;
MGAdac->ClockFrom = X_PROBED;
}
else
{
switch( pMga->Chipset )
{
case PCI_CHIP_MGA1064:
if ( pMga->ChipRev < 3 )
MGAdac->maxPixelClock = 170000;
else
MGAdac->maxPixelClock = 220000;
break;
case PCI_CHIP_MGAG400:
case PCI_CHIP_MGAG550:
MGAdac->maxPixelClock = pMga->Bios2.RamdacType * 4000;
if(MGAdac->maxPixelClock < 300000)
MGAdac->maxPixelClock = 300000;
break;
default:
MGAdac->maxPixelClock = 250000;
}
MGAdac->ClockFrom = X_DEFAULT;
}
pMga->Interleave = FALSE;
pMga->Roundings[0] = 64;
pMga->Roundings[1] = 32;
pMga->Roundings[2] = 64;
pMga->Roundings[3] = 32;
pMga->HasFBitBlt = FALSE;
}
void MGAGSetupFuncs(ScrnInfoPtr pScrn)
{
MGAPtr pMga = MGAPTR(pScrn);
pMga->PreInit = MGAGRamdacInit;
pMga->Save = MGAGSave;
pMga->Restore = MGAGRestore;
pMga->ModeInit = MGAGInit;
pMga->ddc1Read = MGAG_ddc1Read;
pMga->DDC1SetSpeed = vgaHWddc1SetSpeed;
pMga->i2cInit = MGAG_i2cInit;
}