xenocara/driver/xf86-video-ast/src/ast_vgatool.c

3469 lines
95 KiB
C

/*
* Copyright (c) 2005 ASPEED Technology Inc.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of the authors not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. The authors makes no representations
* about the suitability of this software for any purpose. It is provided
* "as is" without express or implied warranty.
*
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "xf86.h"
#include "xf86_OSproc.h"
#include "xf86cmap.h"
#include "compiler.h"
#include "vgaHW.h"
#include "mipointer.h"
#include "micmap.h"
#include "fb.h"
#include "regionstr.h"
#include "xf86xv.h"
#include <X11/extensions/Xv.h>
#include "xf86Pci.h"
/* framebuffer offscreen manager */
#include "xf86fbman.h"
/* include xaa includes */
#include "xaarop.h"
/* H/W cursor support */
#include "xf86Cursor.h"
/* usleep() */
#include <unistd.h>
/* Driver specific headers */
#include "ast.h"
#include "ast_vgatool.h"
#include "ast_dp501fw.h"
__inline ULONG MIndwm(UCHAR *mmiobase, ULONG r)
{
ULONG ulData;
*(ULONG *) (mmiobase + 0xF004) = r & 0xFFFF0000;
*(ULONG *) (mmiobase + 0xF000) = 0x1;
do {
ulData = *(volatile ULONG *) (mmiobase + 0xF004) & 0xFFFF0000;
} while (ulData != (r & 0xFFFF0000) );
return ( *(volatile ULONG *) (mmiobase + 0x10000 + (r & 0x0000FFFF)) );
}
__inline void MOutdwm(UCHAR *mmiobase, ULONG r, ULONG v)
{
ULONG ulData;
*(ULONG *) (mmiobase + 0xF004) = r & 0xFFFF0000;
*(ULONG *) (mmiobase + 0xF000) = 0x1;
do {
ulData = *(volatile ULONG *) (mmiobase + 0xF004) & 0xFFFF0000;
} while (ulData != (r & 0xFFFF0000) );
*(volatile ULONG *) (mmiobase + 0x10000 + (r & 0x0000FFFF)) = v;
}
/*
* BMCI2C
*/
#define I2C_BASE 0x1e780000
static ULONG GetFWBase(ScrnInfoPtr pScrn)
{
ASTRecPtr pAST = ASTPTR(pScrn);
UCHAR *mmiobase;
mmiobase = pAST->MMIOVirtualAddr;
return (MIndwm(mmiobase, 0x1e6e2104) & 0x7FFFFFFF);
}
static void send_ack(ScrnInfoPtr pScrn)
{
ASTRecPtr pAST = ASTPTR(pScrn);
UCHAR SendACK;
GetIndexRegMask(CRTC_PORT, 0x9b, 0xFF, SendACK);
SendACK |= 0x80;
SetIndexRegMask(CRTC_PORT, 0x9B, 0x00, SendACK);
}
static void send_nack(ScrnInfoPtr pScrn)
{
ASTRecPtr pAST = ASTPTR(pScrn);
UCHAR SendACK;
GetIndexRegMask(CRTC_PORT, 0x9b, 0xFF, SendACK);
SendACK &= ~0x80;
SetIndexRegMask(CRTC_PORT, 0x9B, 0x00, SendACK);
}
static Bool wait_ack(ScrnInfoPtr pScrn)
{
ASTRecPtr pAST = ASTPTR(pScrn);
UCHAR WaitACK;
ULONG retry=0;
do {
GetIndexRegMask(CRTC_PORT, 0xd2, 0xFF, WaitACK);
WaitACK &= 0x80;
DelayUS(100);
} while ( (!WaitACK) && (retry++ < 1000) );
if (retry < 1000)
return TRUE;
else
return FALSE;
}
static Bool wait_nack(ScrnInfoPtr pScrn)
{
ASTRecPtr pAST = ASTPTR(pScrn);
UCHAR WaitACK;
ULONG retry=0;
do {
GetIndexRegMask(CRTC_PORT, 0xd2, 0xFF, WaitACK);
WaitACK &= 0x80;
DelayUS(100);
} while ( (WaitACK) && (retry++ < 1000) );
if (retry < 1000)
return TRUE;
else
return FALSE;
}
static void set_cmd_trigger(ScrnInfoPtr pScrn)
{
ASTRecPtr pAST = ASTPTR(pScrn);
SetIndexRegMask(CRTC_PORT, 0x9B, ~0x40, 0x40);
}
static void clear_cmd_trigger(ScrnInfoPtr pScrn)
{
ASTRecPtr pAST = ASTPTR(pScrn);
SetIndexRegMask(CRTC_PORT, 0x9B, ~0x40, 0x00);
}
static Bool write_cmd(ScrnInfoPtr pScrn, UCHAR data)
{
ASTRecPtr pAST = ASTPTR(pScrn);
UCHAR retry = 0;
if (wait_nack(pScrn))
{
send_nack(pScrn);
SetIndexRegMask(CRTC_PORT, 0x9a, 0x00, data);
send_ack(pScrn);
set_cmd_trigger(pScrn);
do {
if (wait_ack(pScrn))
{
clear_cmd_trigger(pScrn);
send_nack(pScrn);
return TRUE;
}
} while (retry++ < 100);
}
clear_cmd_trigger(pScrn);
send_nack(pScrn);
return FALSE;
}
static Bool write_data(ScrnInfoPtr pScrn, UCHAR data)
{
ASTRecPtr pAST = ASTPTR(pScrn);
if (wait_nack(pScrn))
{
send_nack(pScrn);
SetIndexRegMask(CRTC_PORT, 0x9a, 0x00, data);
send_ack(pScrn);
if (wait_ack(pScrn))
{
send_nack(pScrn);
return TRUE;
}
}
send_nack(pScrn);
return FALSE;
}
static void SetDP501VideoOutput(ScrnInfoPtr pScrn, UCHAR Mode)
{
write_cmd(pScrn, 0x40);
write_data(pScrn, Mode);
DelayMS(10); /* delay 10ms */
} /* SetDP501VideoOutput */
static BOOL BackupM68KFW(ScrnInfoPtr pScrn, UCHAR *addr, ULONG size)
{
ASTRecPtr pAST = ASTPTR(pScrn);
UCHAR *mmiobase = pAST->MMIOVirtualAddr;
ULONG i, Data;
ULONG BootAddress;
Data = MIndwm(mmiobase, 0x1e6e2100) & 0x01;
if (Data) /* FW had been load */
{
/* copy image to buffer */
BootAddress = GetFWBase(pScrn);
for (i=0; i<size; i+=4)
{
*(ULONG *)(addr + i) = MIndwm(mmiobase, BootAddress + i);
}
return TRUE;
} /* UEFI Driver Handling */
return FALSE;
} /* BackupM68KFW */
static BOOL LaunchM68K(ScrnInfoPtr pScrn)
{
ASTRecPtr pAST = ASTPTR(pScrn);
UCHAR *mmiobase = pAST->MMIOVirtualAddr;
ULONG i, Data, Len;
ULONG BootAddress;
UCHAR *pFWAddr;
UCHAR jReg;
Data = MIndwm(mmiobase, 0x1e6e2100) & 0x03;
if (Data != 0x01) /* UEFI Driver Handling */
{
/* Reset Co-processor */
MOutdwm(mmiobase, 0x1e6e2100, 0x03);
do {
Data = MIndwm(mmiobase, 0x1e6e2100);
} while (Data != 0x03);
if (pAST->pDP501FWBufferVirtualAddress)
{
pFWAddr = pAST->pDP501FWBufferVirtualAddress;
Len = 32*1024; /* 32K */
}
else
{
pFWAddr = AST_DP501_firmware;
Len = sizeof(AST_DP501_firmware) / sizeof(AST_DP501_firmware[0]);
}
/* Get BootAddress */
MOutdwm(mmiobase, 0x1e6e2000, 0x1688a8a8); /* open passwd */
Data = MIndwm(mmiobase, 0x1e6e0004);
switch (Data & 0x03)
{
case 0x00: /* 64M */
BootAddress = 0x44000000;
break;
default:
case 0x01: /* 128MB */
BootAddress = 0x48000000;
break;
case 0x02: /* 256MB */
BootAddress = 0x50000000;
break;
case 0x03: /* 512MB */
BootAddress = 0x60000000;
break;
}
BootAddress -= 0x200000; /* - 2MB */
/* copy image to buffer */
for (i=0; i<Len; i+=4)
{
Data = *(ULONG *)(pFWAddr + i);
MOutdwm(mmiobase, BootAddress + i, Data);
}
/* Init SCU */
MOutdwm(mmiobase, 0x1e6e2000, 0x1688a8a8); /* open passwd */
/* Launch FW */
MOutdwm(mmiobase, 0x1e6e2104, 0x80000000 + BootAddress);
MOutdwm(mmiobase, 0x1e6e2100, 1);
/* Update Scratch */
Data = MIndwm(mmiobase, 0x1e6e2040) & 0xFFFFF1FF; /* D[11:9] = 100b: UEFI handling */
Data |= 0x0800;
MOutdwm(mmiobase, 0x1e6e2040, Data);
GetIndexRegMask(CRTC_PORT, 0x99, 0xFC, jReg); /* D[1:0]: Reserved Video Buffer */
jReg |= 0x02; /* 2MB */
SetIndexReg(CRTC_PORT, 0x99, jReg);
} /* UEFI Driver Handling */
return TRUE;
} /* LaunchM68K */
/*
* DP501 external
*/
Bool ASTReadEDID_M68K(ScrnInfoPtr pScrn, BYTE *pEDIDData)
{
ASTRecPtr pAST = ASTPTR(pScrn);
UCHAR *mmiobase;
ULONG i, BootAddress, Offset, Data;
/* init value */
mmiobase = pAST->MMIOVirtualAddr;
BootAddress = GetFWBase(pScrn);
/* validate FW version */
Offset = 0xF000;
Data = MIndwm(mmiobase, BootAddress + Offset);
if ((Data & 0xF0) != 0x10) /* version: 1x */
return FALSE;
/* validate PnP Monitor */
Offset = 0xF010;
Data = MIndwm(mmiobase, BootAddress + Offset);
if (!(Data & 0x01))
return FALSE;
/* Read EDID */
Offset = 0xF020;
for (i=0; i<128; i+=4)
{
Data = MIndwm(mmiobase, BootAddress + Offset + i);
*(ULONG *)(pEDIDData + i) = Data;
}
return TRUE;
} /* ReadEDID_M68K */
UCHAR ASTGetLinkMaxCLK(ScrnInfoPtr pScrn)
{
ASTRecPtr pAST = ASTPTR(pScrn);
UCHAR *mmiobase;
ULONG BootAddress, Offset, Data;
UCHAR LinkCap[4], LinkRate, LinkLanes, MaxClk = 0xFF;
/* init value */
mmiobase = pAST->MMIOVirtualAddr;
BootAddress = GetFWBase(pScrn);
/* validate FW version */
Offset = 0xF000;
Data = MIndwm(mmiobase, BootAddress + Offset);
if ((Data & 0xF0) != 0x10) /* version: 1x */
return MaxClk;
/* Read Link Capability */
Offset = 0xF014;
*(ULONG *)(LinkCap) = MIndwm(mmiobase, BootAddress + Offset);
if (LinkCap[2] == 0) /* no Max. CLK Assigned */
{
LinkRate = LinkCap[0];
LinkLanes = LinkCap[1];
Data = (LinkRate == 0x0A) ? (90 * LinkLanes): (54 * LinkLanes);
if (Data > 255) Data = 255; /* Max. */
MaxClk = (UCHAR)(Data);
}
return MaxClk;
} /* ASTGetLinkMaxCLK */
/*
* VGA Modules
*/
void
vASTOpenKey(ScrnInfoPtr pScrn)
{
ASTRecPtr pAST = ASTPTR(pScrn);
SetIndexReg(CRTC_PORT,0x80, 0xA8);
}
Bool
bASTRegInit(ScrnInfoPtr pScrn)
{
ASTRecPtr pAST = ASTPTR(pScrn);
/* Enable MMIO */
SetIndexRegMask(CRTC_PORT,0xA1, 0xFF, 0x04);
/* Enable Big-Endian */
#if defined(__sparc__)
SetIndexRegMask(CRTC_PORT,0xA2, 0xFF, 0x80);
#endif
return (TRUE);
}
void
ASTGetDRAMInfo(ScrnInfoPtr pScrn)
{
ASTRecPtr pAST = ASTPTR(pScrn);
ULONG ulRefPLL, ulDeNumerator, ulNumerator, ulDivider;
ULONG ulData, ulData2;
*(ULONG *) (pAST->MMIOVirtualAddr + 0xF004) = 0x1e6e0000;
*(ULONG *) (pAST->MMIOVirtualAddr + 0xF000) = 0x1;
*(ULONG *) (pAST->MMIOVirtualAddr + 0x10000) = 0xFC600309;
do {
;
} while (*(volatile ULONG *) (pAST->MMIOVirtualAddr + 0x10000) != 0x01);
ulData = *(volatile ULONG *) (pAST->MMIOVirtualAddr + 0x10004);
/* Get BusWidth */
if (ulData & 0x40)
pAST->ulDRAMBusWidth = 16;
else
pAST->ulDRAMBusWidth = 32;
/* Get DRAM Type */
if ((pAST->jChipType == AST2300) || (pAST->jChipType == AST2400))
{
switch (ulData & 0x03)
{
case 0x00:
pAST->jDRAMType = DRAMTYPE_512Mx16;
break;
default:
case 0x01:
pAST->jDRAMType = DRAMTYPE_1Gx16;
break;
case 0x02:
pAST->jDRAMType = DRAMTYPE_2Gx16;
break;
case 0x03:
pAST->jDRAMType = DRAMTYPE_4Gx16;
break;
}
}
else
{
switch (ulData & 0x0C)
{
case 0x00:
case 0x04:
pAST->jDRAMType = DRAMTYPE_512Mx16;
break;
case 0x08:
if (ulData & 0x40) /* 16bits */
pAST->jDRAMType = DRAMTYPE_1Gx16;
else /* 32bits */
pAST->jDRAMType = DRAMTYPE_512Mx32;
break;
case 0x0C:
pAST->jDRAMType = DRAMTYPE_1Gx32;
break;
}
}
/* Get MCLK */
ulData = *(ULONG *) (pAST->MMIOVirtualAddr + 0x10120);
ulData2 = *(ULONG *) (pAST->MMIOVirtualAddr + 0x10170);
if (ulData2 & 0x2000)
ulRefPLL = 14318;
else
ulRefPLL = 12000;
ulDeNumerator = ulData & 0x1F;
ulNumerator = (ulData & 0x3FE0) >> 5;
ulData = (ulData & 0xC000) >> 14;
switch (ulData)
{
case 0x03:
ulDivider = 0x04;
break;
case 0x02:
case 0x01:
ulDivider = 0x02;
break;
default:
ulDivider = 0x01;
}
pAST->ulMCLK = ulRefPLL * (ulNumerator + 2) / ((ulDeNumerator + 2) * ulDivider * 1000);
} /* ASTGetDRAMInfo */
ULONG
ASTGetVRAMInfo(ScrnInfoPtr pScrn)
{
ASTRecPtr pAST = ASTPTR(pScrn);
ULONG ulVRAMSize;
UCHAR jReg;
vASTOpenKey(pScrn);
/* Get VRAMSize from H/W Trapping */
GetIndexRegMask(CRTC_PORT, 0xAA, 0xFF, jReg);
switch (jReg & 0x03)
{
default:
case 0x00:
ulVRAMSize = VIDEOMEM_SIZE_08M;
break;
case 0x01:
ulVRAMSize = VIDEOMEM_SIZE_16M;
break;
case 0x02:
ulVRAMSize = VIDEOMEM_SIZE_32M;
break;
case 0x03:
ulVRAMSize = VIDEOMEM_SIZE_64M;
break;
}
/* Adjust VRAMSize from Scratch */
GetIndexRegMask(CRTC_PORT, 0x99, 0xFF, jReg);
switch (jReg & 0x03)
{
case 0x01:
ulVRAMSize -= 0x100000;
break;
case 0x02:
ulVRAMSize -= 0x200000;
break;
case 0x03:
ulVRAMSize -= 0x400000;
break;
}
return (ulVRAMSize);
}
ULONG
ASTGetMaxDCLK(ScrnInfoPtr pScrn)
{
ASTRecPtr pAST = ASTPTR(pScrn);
UCHAR jReg;
ULONG ulDRAMBusWidth, ulMCLK, ulDRAMBandwidth, ActualDRAMBandwidth, DRAMEfficiency = 500;
ULONG ulDCLK;
ulMCLK = pAST->ulMCLK;
ulDRAMBusWidth = pAST->ulDRAMBusWidth;
/* Get Bandwidth */
/* Modify DARM utilization to 60% for AST1100/2100 16bits DRAM, ycchen@032508 */
if ( ((pAST->jChipType == AST2100) || (pAST->jChipType == AST1100) || (pAST->jChipType == AST2200) || (pAST->jChipType == AST2150)) && (ulDRAMBusWidth == 16) )
DRAMEfficiency = 600;
else if ((pAST->jChipType == AST2300) || (pAST->jChipType == AST2400))
DRAMEfficiency = 400;
ulDRAMBandwidth = ulMCLK * ulDRAMBusWidth * 2 / 8;
ActualDRAMBandwidth = ulDRAMBandwidth * DRAMEfficiency / 1000;
/* Get Max DCLK */
if (pAST->jChipType == AST1180)
{
ulDCLK = ActualDRAMBandwidth / ((pScrn->bitsPerPixel+1) / 8);
}
else
{
/* Fixed Fixed KVM + CRT threshold issue on AST2100 8bpp modes, ycchen@100708 */
GetIndexRegMask(CRTC_PORT, 0xD0, 0xFF, jReg);
if ((jReg & 0x08) && (pAST->jChipType == AST2000))
ulDCLK = ActualDRAMBandwidth / ((pScrn->bitsPerPixel+1+16) / 8);
else if ((jReg & 0x08) && (pScrn->bitsPerPixel == 8))
ulDCLK = ActualDRAMBandwidth / ((pScrn->bitsPerPixel+1+24) / 8);
else
ulDCLK = ActualDRAMBandwidth / ((pScrn->bitsPerPixel+1) / 8);
}
/* Validate for DP501 */
if (pAST->jTxChipType == Tx_DP501)
{
if (ulDCLK > pAST->DP501_MaxVCLK) ulDCLK = pAST->DP501_MaxVCLK;
}
/* Add for AST2100, ycchen@061807 */
if ((pAST->jChipType == AST2100) || (pAST->jChipType == AST2200) || (pAST->jChipType == AST2300) || (pAST->jChipType == AST2400) || (pAST->jChipType == AST1180) )
{
if (ulDCLK > 200) ulDCLK = 200;
}
else
{
if (ulDCLK > 165) ulDCLK = 165;
}
return(ulDCLK);
}
void
ASTGetChipType(ScrnInfoPtr pScrn)
{
ASTRecPtr pAST = ASTPTR(pScrn);
ULONG ulData;
pAST->jChipType = AST2100;
*(ULONG *) (pAST->MMIOVirtualAddr + 0xF004) = 0x1e6e0000;
*(ULONG *) (pAST->MMIOVirtualAddr + 0xF000) = 0x1;
ulData = *(ULONG *) (pAST->MMIOVirtualAddr + 0x1207c);
switch (ulData & 0x0300)
{
case 0x0200:
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "AST1100 Detected.\n");
pAST->jChipType = AST1100;
break;
case 0x0100:
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "AST2200 Detected.\n");
pAST->jChipType = AST2200;
break;
case 0x0000:
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "AST2150 Detected.\n");
pAST->jChipType = AST2150;
break;
default:
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "AST2100 Detected.\n");
pAST->jChipType = AST2100;
}
}
void
ASTGetScratchOptions(ScrnInfoPtr pScrn)
{
ASTRecPtr pAST = ASTPTR(pScrn);
ULONG ulData;
UCHAR jReg;
/* VGA2 Clone Support */
GetIndexRegMask(CRTC_PORT, 0x90, 0xFF, jReg);
if (jReg & 0x10)
pAST->VGA2Clone = TRUE;
/* 3rd Tx Check */
pAST->pDP501FWBufferVirtualAddress = NULL;
pAST->jTxChipType = Tx_NONE;
/* Get 3rd Tx Info from HW Reg. */
GetIndexRegMask(CRTC_PORT, 0xA3, 0xFF, jReg);
if (jReg & 0x80)
pAST->jTxChipType = Tx_Sil164;
/* Get 3rd Tx Info from BMC Scratch */
if ((pAST->jChipType == AST2300) || (pAST->jChipType == AST2400))
{
GetIndexRegMask(CRTC_PORT, 0xD1, 0x0E, jReg);
switch (jReg)
{
case 0x04:
pAST->jTxChipType = Tx_Sil164;
break;
case 0x08:
pAST->pDP501FWBufferVirtualAddress = (UCHAR*) calloc(1, 32*1024);
if (pAST->pDP501FWBufferVirtualAddress)
{
if (BackupM68KFW(pScrn, pAST->pDP501FWBufferVirtualAddress, 32*1024) == FALSE)
{
free(pAST->pDP501FWBufferVirtualAddress);
pAST->pDP501FWBufferVirtualAddress = NULL;
}
} /* Backup DP501 FW */
case 0x0c:
pAST->jTxChipType = Tx_DP501;
break;
}
}
/* WideScreen Support */
switch (pAST->jChipType)
{
case AST1180:
pAST->SupportWideScreen = TRUE;
break;
case AST2000:
pAST->SupportWideScreen = FALSE;
break;
default:
GetIndexRegMask(CRTC_PORT, 0xD0, 0xFF, jReg);
if (!(jReg & 0x80))
pAST->SupportWideScreen = TRUE;
else if (jReg & 0x01)
pAST->SupportWideScreen = TRUE;
else
{
pAST->SupportWideScreen = FALSE;
*(ULONG *) (pAST->MMIOVirtualAddr + 0xF004) = 0x1e6e0000;
*(ULONG *) (pAST->MMIOVirtualAddr + 0xF000) = 0x1;
ulData = *(ULONG *) (pAST->MMIOVirtualAddr + 0x1207c);
ulData &= 0x0300;
if ((pAST->jChipType == AST2300) && (ulData == 0x0000)) /* AST1300 */
pAST->SupportWideScreen = TRUE;
if ((pAST->jChipType == AST2400) && (ulData == 0x0100)) /* AST1400 */
pAST->SupportWideScreen = TRUE;
}
} /* switch case */
} /* GetScratchOptions */
void
vASTSetStartAddressCRT1(ASTRecPtr pAST, ULONG base)
{
ULONG addr;
if (pAST->jChipType == AST1180)
{
addr = pAST->ulVRAMBase + base;
WriteAST1180SOC(AST1180_GFX_BASE + AST1180_VGA1_STARTADDR, addr);
}
else
{
addr = base >> 2; /* DW unit */
SetIndexReg(CRTC_PORT,0x0D, (UCHAR) (addr & 0xFF));
SetIndexReg(CRTC_PORT,0x0C, (UCHAR) ((addr >> 8) & 0xFF));
SetIndexReg(CRTC_PORT,0xAF, (UCHAR) ((addr >> 16) & 0xFF));
}
}
void
vAST1000DisplayOff(ScrnInfoPtr pScrn)
{
ASTRecPtr pAST = ASTPTR(pScrn);
ULONG ulData;
/* 3rd Tx */
if (pAST->jTxChipType == Tx_DP501)
SetDP501VideoOutput(pScrn, 0);
if (pAST->jChipType == AST1180)
{
ReadAST1180SOC(AST1180_GFX_BASE + AST1180_VGA1_CTRL, ulData);
ulData |= 0x00100000;
WriteAST1180SOC(AST1180_GFX_BASE + AST1180_VGA1_CTRL, ulData);
}
else
SetIndexRegMask(SEQ_PORT,0x01, 0xDF, 0x20);
}
void
vAST1000DisplayOn(ScrnInfoPtr pScrn)
{
ASTRecPtr pAST = ASTPTR(pScrn);
ULONG ulData;
if (pAST->jChipType == AST1180)
{
ReadAST1180SOC(AST1180_GFX_BASE + AST1180_VGA1_CTRL, ulData);
ulData &= 0xFFEFFFFF;
WriteAST1180SOC(AST1180_GFX_BASE + AST1180_VGA1_CTRL, ulData);
}
else
SetIndexRegMask(SEQ_PORT,0x01, 0xDF, 0x00);
/* 3rd Tx */
if (pAST->jTxChipType == Tx_DP501)
SetDP501VideoOutput(pScrn, 1);
}
void ASTBlankScreen(ScrnInfoPtr pScrn, Bool unblack)
{
if (unblack)
vAST1000DisplayOn(pScrn);
else
vAST1000DisplayOff(pScrn);
}
void
vASTLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors,
VisualPtr pVisual)
{
ASTRecPtr pAST = ASTPTR(pScrn);
int i, j, index;
UCHAR DACIndex, DACR, DACG, DACB;
switch (pScrn->bitsPerPixel) {
case 15:
for(i=0; i<numColors; i++) {
index = indices[i];
for(j=0; j<8; j++) {
DACIndex = (index * 8) + j;
DACR = colors[index].red << (8- pScrn->rgbBits);
DACG = colors[index].green << (8- pScrn->rgbBits);
DACB = colors[index].blue << (8- pScrn->rgbBits);
VGA_LOAD_PALETTE_INDEX (DACIndex, DACR, DACG, DACB);
}
}
break;
case 16:
for(i=0; i<numColors; i++) {
index = indices[i];
for(j=0; j<4; j++) {
DACIndex = (index * 4) + j;
DACR = colors[index/2].red << (8- pScrn->rgbBits);
DACG = colors[index].green << (8- pScrn->rgbBits);
DACB = colors[index/2].blue << (8- pScrn->rgbBits);
VGA_LOAD_PALETTE_INDEX (DACIndex, DACR, DACG, DACB);
}
}
break;
case 24:
for(i=0; i<numColors; i++) {
index = indices[i];
DACIndex = index;
DACR = colors[index].red;
DACG = colors[index].green;
DACB = colors[index].blue;
VGA_LOAD_PALETTE_INDEX (DACIndex, DACR, DACG, DACB);
}
break;
default:
for(i=0; i<numColors; i++) {
index = indices[i];
DACIndex = index;
DACR = colors[index].red >> (8 - pScrn->rgbBits);
DACG = colors[index].green >> (8 - pScrn->rgbBits);
DACB = colors[index].blue >> (8 - pScrn->rgbBits);
VGA_LOAD_PALETTE_INDEX (DACIndex, DACR, DACG, DACB);
}
} /* end of switch */
} /* end of vASTLoadPalette */
void
ASTDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags)
{
ASTRecPtr pAST;
UCHAR SEQ01, CRB6;
ULONG ulData, ulTemp;
pAST = ASTPTR(pScrn);
SEQ01=CRB6=0;
ulData = 0;
vASTOpenKey(pScrn);
switch (PowerManagementMode) {
case DPMSModeOn:
/* Screen: On; HSync: On, VSync: On */
SEQ01 = 0x00;
CRB6 = 0x00;
ulData = 0x00000000;
break;
case DPMSModeStandby:
/* Screen: Off; HSync: Off, VSync: On */
SEQ01 = 0x20;
CRB6 = 0x01;
ulData = 0x00140000;
break;
case DPMSModeSuspend:
/* Screen: Off; HSync: On, VSync: Off */
SEQ01 = 0x20;
CRB6 = 0x02;
ulData = 0x00180000;
break;
case DPMSModeOff:
/* Screen: Off; HSync: Off, VSync: Off */
SEQ01 = 0x20;
CRB6 = 0x03;
ulData = 0x001C0000;
break;
}
if (PowerManagementMode != DPMSModeOn)
{ /* 3rd Tx */
if (pAST->jTxChipType == Tx_DP501) SetDP501VideoOutput(pScrn, 0);
}
if (pAST->jChipType == AST1180)
{
ReadAST1180SOC(AST1180_GFX_BASE + AST1180_VGA1_CTRL, ulTemp);
ulTemp &= 0xFFE3FFFF;
ulTemp |= ulData;
WriteAST1180SOC(AST1180_GFX_BASE + AST1180_VGA1_CTRL, ulTemp);
}
else
{
SetIndexRegMask(SEQ_PORT,0x01, 0xDF, SEQ01);
SetIndexRegMask(CRTC_PORT,0xB6, 0xFC, CRB6);
}
if (PowerManagementMode == DPMSModeOn)
{ /* 3rd Tx */
if (pAST->jTxChipType == Tx_DP501) SetDP501VideoOutput(pScrn, 1);
}
}
#ifndef I2C_BASE
#define I2C_BASE 0x1e780000
#endif
#define I2C_OFFSET (0xA000 + 0x40 * 4) /* port4 */
#define I2C_DEVICEADDR 0x0A0 /* slave addr */
#define I2C_BASE_AST1180 0x80fc0000
#define I2C_OFFSET_AS1180 (0xB000 + 0x40 * 2) /* port2 */
#define I2C_DEVICEADDR_AST1180 0x0A0 /* slave addr */
Bool
ASTGetVGA2EDID(ScrnInfoPtr pScrn, unsigned char *pEDIDBuffer)
{
ASTRecPtr pAST = ASTPTR(pScrn);
ULONG i, ulData;
UCHAR *pjEDID;
ULONG base, deviceaddr;
UCHAR *offset;
pjEDID = pEDIDBuffer;
if (pAST->jChipType == AST1180)
{
base = I2C_BASE_AST1180;
offset = pAST->MMIOVirtualAddr + 0x10000 + I2C_OFFSET_AS1180;
deviceaddr = I2C_DEVICEADDR_AST1180;
}
else
{
base = I2C_BASE;
offset = pAST->MMIOVirtualAddr + 0x10000 + I2C_OFFSET;
deviceaddr = I2C_DEVICEADDR;
/* SCU settings */
*(ULONG *) (pAST->MMIOVirtualAddr + 0xF004) = 0x1e6e0000;
*(ULONG *) (pAST->MMIOVirtualAddr + 0xF000) = 0x1;
usleep(10000);
*(ULONG *) (pAST->MMIOVirtualAddr + 0x12000) = 0x1688A8A8;
ulData = *(ULONG *) (pAST->MMIOVirtualAddr + 0x12004);
ulData &= 0xfffffffb;
*(ULONG *) (pAST->MMIOVirtualAddr + 0x12004) = ulData;
usleep(10000);
}
/* I2C settings */
*(ULONG *) (pAST->MMIOVirtualAddr + 0xF004) = base;
*(ULONG *) (pAST->MMIOVirtualAddr + 0xF000) = 0x1;
usleep(10000);
/* I2C Start */
*(ULONG *) (offset + 0x00) = 0x0;
*(ULONG *) (offset + 0x04) = 0x77777355;
*(ULONG *) (offset + 0x08) = 0x0;
*(ULONG *) (offset + 0x10) = 0xffffffff;
*(ULONG *) (offset + 0x00) = 0x1;
*(ULONG *) (offset + 0x0C) = 0xAF;
*(ULONG *) (offset + 0x20) = deviceaddr;
*(ULONG *) (offset + 0x14) = 0x03;
do {
ulData = *(volatile ULONG *) (offset + 0x10);
} while (!(ulData & 0x03));
if (ulData & 0x02) /* NACK */
return (FALSE);
*(ULONG *) (offset + 0x10) = 0xffffffff;
*(ULONG *) (offset + 0x20) = (ULONG) 0; /* Offset */
*(ULONG *) (offset + 0x14) = 0x02;
do {
ulData = *(volatile ULONG *) (offset + 0x10);
} while (!(ulData & 0x01));
*(ULONG *) (offset + 0x10) = 0xffffffff;
*(ULONG *) (offset + 0x20) = deviceaddr + 1;
*(ULONG *) (offset + 0x14) = 0x03;
do {
ulData = *(volatile ULONG *) (offset + 0x10);
} while (!(ulData & 0x01));
/* I2C Read */
for (i=0; i<127; i++)
{
*(ULONG *) (offset + 0x10) = 0xffffffff;
*(ULONG *) (offset + 0x0C) |= 0x10;
*(ULONG *) (offset + 0x14) = 0x08;
do {
ulData = *(volatile ULONG *) (offset + 0x10);
} while (!(ulData & 0x04));
*(ULONG *) (offset + 0x10) = 0xffffffff;
*(UCHAR *) (pjEDID++) = (UCHAR) ((*(ULONG *) (offset + 0x20) & 0xFF00) >> 8);
}
/* Read Last Byte */
*(ULONG *) (offset + 0x10) = 0xffffffff;
*(ULONG *) (offset + 0x0C) |= 0x10;
*(ULONG *) (offset + 0x14) = 0x18;
do {
ulData = *(volatile ULONG *) (offset + 0x10);
} while (!(ulData & 0x04));
*(ULONG *) (offset + 0x10) = 0xffffffff;
*(UCHAR *) (pjEDID++) = (UCHAR) ((*(ULONG *) (offset + 0x20) & 0xFF00) >> 8);
/* I2C Stop */
*(ULONG *) (offset + 0x10) = 0xffffffff;
*(ULONG *) (offset + 0x14) = 0x20;
do {
ulData = *(volatile ULONG *) (offset + 0x10);
} while (!(ulData & 0x10));
*(ULONG *) (offset + 0x0C) &= 0xffffffef;
*(ULONG *) (offset + 0x10) = 0xffffffff;
return (TRUE);
} /* ASTGetVGA2EDID */
/* Init VGA */
Bool bASTIsVGAEnabled(ScrnInfoPtr pScrn)
{
ASTRecPtr pAST;
UCHAR ch;
ULONG ulData;
pAST = ASTPTR(pScrn);
if (pAST->jChipType == AST1180)
{
WriteAST1180SOC(AST1180_MMC_BASE+0x00, 0xFC600309); /* unlock */
ReadAST1180SOC(AST1180_MMC_BASE+0x08, ulData);
return (ulData);
}
else
{
ch = inb(pAST->RelocateIO + 0x43);
if (ch == 0x01)
{
outw(pAST->RelocateIO + 0x54, 0xa880);
outb(pAST->RelocateIO + 0x54, 0xb6);
ch = inb(pAST->RelocateIO + 0x55);
return (ch & 0x04);
}
}
return (0);
}
static void vEnableVGA(ScrnInfoPtr pScrn)
{
ASTRecPtr pAST;
pAST = ASTPTR(pScrn);
SetReg(VGA_ENABLE_PORT, 0x01);
SetReg(MISC_PORT_WRITE, 0x01);
}
static UCHAR ExtRegInfo[] = {
0x0F,
0x04,
0x1C,
0xFF
};
static UCHAR ExtRegInfo_AST2300A0[] = {
0x0F,
0x04,
0x1C,
0xFF
};
static UCHAR ExtRegInfo_AST2300[] = {
0x0F,
0x04,
0x1F,
0xFF
};
static void vSetDefExtReg(ScrnInfoPtr pScrn)
{
ASTRecPtr pAST;
UCHAR i, jIndex, jReg, *pjExtRegInfo;
pAST = ASTPTR(pScrn);
/* Reset Scratch */
for (i=0x81; i<=0x8F; i++)
{
SetIndexReg(CRTC_PORT, i, 0x00);
}
/* Set Ext. Reg */
if ((pAST->jChipType == AST2300) || (pAST->jChipType == AST2400))
{
if (PCI_DEV_REVISION(pAST->PciInfo) > 0x20)
pjExtRegInfo = ExtRegInfo_AST2300;
else
pjExtRegInfo = ExtRegInfo_AST2300A0;
}
else
pjExtRegInfo = ExtRegInfo;
jIndex = 0xA0;
while (*(UCHAR *) (pjExtRegInfo) != 0xFF)
{
SetIndexRegMask(CRTC_PORT,jIndex, 0x00, *(UCHAR *) (pjExtRegInfo));
jIndex++;
pjExtRegInfo++;
}
/* disable standard IO/MEM decode if secondary */
if (!xf86IsPrimaryPci(pAST->PciInfo))
SetIndexRegMask(CRTC_PORT,0xA1, 0xFF, 0x03);
/* Set Ext. Default */
SetIndexRegMask(CRTC_PORT,0x8C, 0x00, 0x01);
SetIndexRegMask(CRTC_PORT,0xB7, 0x00, 0x00);
/* Enable RAMDAC for A1, ycchen@113005 */
jReg = 0x04;
if ((pAST->jChipType == AST2300) || (pAST->jChipType == AST2400))
jReg |= 0x20;
SetIndexRegMask(CRTC_PORT,0xB6, 0xFF, jReg);
}
/*
* AST2100/2150 DLL CBR Setting
*/
#define CBR_SIZE_AST2150 ((16 << 10) - 1)
#define CBR_PASSNUM_AST2150 5
#define CBR_THRESHOLD_AST2150 10
#define CBR_THRESHOLD2_AST2150 10
#define TIMEOUT_AST2150 5000000
#define CBR_PATNUM_AST2150 8
static ULONG pattern_AST2150[14] ={
0xFF00FF00,
0xCC33CC33,
0xAA55AA55,
0xFFFE0001,
0x683501FE,
0x0F1929B0,
0x2D0B4346,
0x60767F02,
0x6FBE36A6,
0x3A253035,
0x3019686D,
0x41C6167E,
0x620152BF,
0x20F050E0};
typedef struct _AST2150DRAMParam {
UCHAR *pjMMIOVirtualAddress;
} AST2150DRAMParam, *PAST2150DRAMParam;
static ULONG MMCTestBurst2_AST2150(PAST2150DRAMParam param, ULONG datagen)
{
ULONG data, timeout;
UCHAR *mmiobase;
mmiobase = param->pjMMIOVirtualAddress;
MOutdwm(mmiobase, 0x1E6E0070, 0x00000000);
MOutdwm(mmiobase, 0x1E6E0070, 0x00000001 | (datagen << 3));
timeout = 0;
do{
data = MIndwm(mmiobase, 0x1E6E0070) & 0x40;
if(++timeout > TIMEOUT_AST2150){
MOutdwm(mmiobase, 0x1E6E0070, 0x00000000);
return(-1);
}
}while(!data);
MOutdwm(mmiobase, 0x1E6E0070, 0x00000000);
MOutdwm(mmiobase, 0x1E6E0070, 0x00000003 | (datagen << 3));
timeout = 0;
do{
data = MIndwm(mmiobase, 0x1E6E0070) & 0x40;
if(++timeout > TIMEOUT_AST2150){
MOutdwm(mmiobase, 0x1E6E0070, 0x00000000);
return(-1);
}
}while(!data);
data = (MIndwm(mmiobase, 0x1E6E0070) & 0x80) >> 7;
MOutdwm(mmiobase, 0x1E6E0070, 0x00000000);
return(data);
}
static ULONG MMCTestSingle2_AST2150(PAST2150DRAMParam param, ULONG datagen)
{
ULONG data, timeout;
UCHAR *mmiobase;
mmiobase = param->pjMMIOVirtualAddress;
MOutdwm(mmiobase, 0x1E6E0070, 0x00000000);
MOutdwm(mmiobase, 0x1E6E0070, 0x00000005 | (datagen << 3));
timeout = 0;
do{
data = MIndwm(mmiobase, 0x1E6E0070) & 0x40;
if(++timeout > TIMEOUT_AST2150){
MOutdwm(mmiobase, 0x1E6E0070, 0x00000000);
return(-1);
}
}while(!data);
data = (MIndwm(mmiobase, 0x1E6E0070) & 0x80) >> 7;
MOutdwm(mmiobase, 0x1E6E0070, 0x00000000);
return(data);
}
static int CBRTest_AST2150(PAST2150DRAMParam param)
{
UCHAR *mmiobase;
mmiobase = param->pjMMIOVirtualAddress;
if(MMCTestBurst2_AST2150(param, 0) ) return(0);
if(MMCTestBurst2_AST2150(param, 1) ) return(0);
if(MMCTestBurst2_AST2150(param, 2) ) return(0);
if(MMCTestBurst2_AST2150(param, 3) ) return(0);
if(MMCTestBurst2_AST2150(param, 4) ) return(0);
if(MMCTestBurst2_AST2150(param, 5) ) return(0);
if(MMCTestBurst2_AST2150(param, 6) ) return(0);
if(MMCTestBurst2_AST2150(param, 7) ) return(0);
return(1);
}
static int CBRScan_AST2150(PAST2150DRAMParam param, int busw)
{
ULONG patcnt, loop;
UCHAR *mmiobase;
mmiobase = param->pjMMIOVirtualAddress;
for(patcnt = 0;patcnt < CBR_PATNUM_AST2150;patcnt++){
MOutdwm(mmiobase, 0x1E6E007C, pattern_AST2150[patcnt]);
for(loop = 0;loop < CBR_PASSNUM_AST2150;loop++){
if(CBRTest_AST2150(param)){
break;
}
}
if(loop == CBR_PASSNUM_AST2150){
return(0);
}
}
return(1);
}
static void CBRDLLI_AST2150(PAST2150DRAMParam param, int busw)
{
ULONG dllmin[4], dllmax[4], dlli, data, passcnt;
UCHAR *mmiobase;
mmiobase = param->pjMMIOVirtualAddress;
CBR_START:
dllmin[0] = dllmin[1] = dllmin[2] = dllmin[3] = 0xff;
dllmax[0] = dllmax[1] = dllmax[2] = dllmax[3] = 0x0;
passcnt = 0;
MOutdwm(mmiobase, 0x1E6E0074, CBR_SIZE_AST2150);
for(dlli = 0;dlli < 100;dlli++){
MOutdwm(mmiobase, 0x1E6E0068, dlli | (dlli << 8) | (dlli << 16) | (dlli << 24));
data = CBRScan_AST2150(param, busw);
if(data != 0){
if(data & 0x1){
if(dllmin[0] > dlli){
dllmin[0] = dlli;
}
if(dllmax[0] < dlli){
dllmax[0] = dlli;
}
}
passcnt++;
}else if(passcnt >= CBR_THRESHOLD_AST2150){
break;
}
}
if(dllmax[0] == 0 || (dllmax[0]-dllmin[0]) < CBR_THRESHOLD_AST2150){
goto CBR_START;
}
dlli = dllmin[0] + (((dllmax[0] - dllmin[0]) * 7) >> 4);
MOutdwm(mmiobase, 0x1E6E0068, dlli | (dlli << 8) | (dlli << 16) | (dlli << 24));
}
typedef struct _AST_DRAMStruct {
USHORT Index;
ULONG Data;
} AST_DRAMStruct, *PAST_DRAMStruct;
static AST_DRAMStruct AST2000DRAMTableData[] = {
{ 0x0108, 0x00000000 },
{ 0x0120, 0x00004a21 },
{ 0xFF00, 0x00000043 },
{ 0x0000, 0xFFFFFFFF },
{ 0x0004, 0x00000089 },
{ 0x0008, 0x22331353 },
{ 0x000C, 0x0d07000b },
{ 0x0010, 0x11113333 },
{ 0x0020, 0x00110350 },
{ 0x0028, 0x1e0828f0 },
{ 0x0024, 0x00000001 },
{ 0x001C, 0x00000000 },
{ 0x0014, 0x00000003 },
{ 0xFF00, 0x00000043 },
{ 0x0018, 0x00000131 },
{ 0x0014, 0x00000001 },
{ 0xFF00, 0x00000043 },
{ 0x0018, 0x00000031 },
{ 0x0014, 0x00000001 },
{ 0xFF00, 0x00000043 },
{ 0x0028, 0x1e0828f1 },
{ 0x0024, 0x00000003 },
{ 0x002C, 0x1f0f28fb },
{ 0x0030, 0xFFFFFE01 },
{ 0xFFFF, 0xFFFFFFFF }
};
static AST_DRAMStruct AST1100DRAMTableData[] = {
{ 0x2000, 0x1688a8a8 },
{ 0x2020, 0x000041f0 },
{ 0xFF00, 0x00000043 },
{ 0x0000, 0xfc600309 },
{ 0x006C, 0x00909090 },
{ 0x0064, 0x00050000 },
{ 0x0004, 0x00000585 },
{ 0x0008, 0x0011030f },
{ 0x0010, 0x22201724 },
{ 0x0018, 0x1e29011a },
{ 0x0020, 0x00c82222 },
{ 0x0014, 0x01001523 },
{ 0x001C, 0x1024010d },
{ 0x0024, 0x00cb2522 },
{ 0x0038, 0xffffff82 },
{ 0x003C, 0x00000000 },
{ 0x0040, 0x00000000 },
{ 0x0044, 0x00000000 },
{ 0x0048, 0x00000000 },
{ 0x004C, 0x00000000 },
{ 0x0050, 0x00000000 },
{ 0x0054, 0x00000000 },
{ 0x0058, 0x00000000 },
{ 0x005C, 0x00000000 },
{ 0x0060, 0x032aa02a },
{ 0x0064, 0x002d3000 },
{ 0x0068, 0x00000000 },
{ 0x0070, 0x00000000 },
{ 0x0074, 0x00000000 },
{ 0x0078, 0x00000000 },
{ 0x007C, 0x00000000 },
{ 0x0034, 0x00000001 },
{ 0xFF00, 0x00000043 },
{ 0x002C, 0x00000732 },
{ 0x0030, 0x00000040 },
{ 0x0028, 0x00000005 },
{ 0x0028, 0x00000007 },
{ 0x0028, 0x00000003 },
{ 0x0028, 0x00000001 },
{ 0x000C, 0x00005a08 },
{ 0x002C, 0x00000632 },
{ 0x0028, 0x00000001 },
{ 0x0030, 0x000003c0 },
{ 0x0028, 0x00000003 },
{ 0x0030, 0x00000040 },
{ 0x0028, 0x00000003 },
{ 0x000C, 0x00005a21 },
{ 0x0034, 0x00007c03 },
{ 0x0120, 0x00004c41 },
{ 0xffff, 0xffffffff },
};
static AST_DRAMStruct AST2100DRAMTableData[] = {
{ 0x2000, 0x1688a8a8 },
{ 0x2020, 0x00004120 },
{ 0xFF00, 0x00000043 },
{ 0x0000, 0xfc600309 },
{ 0x006C, 0x00909090 },
{ 0x0064, 0x00070000 },
{ 0x0004, 0x00000489 },
{ 0x0008, 0x0011030f },
{ 0x0010, 0x32302926 },
{ 0x0018, 0x274c0122 },
{ 0x0020, 0x00ce2222 },
{ 0x0014, 0x01001523 },
{ 0x001C, 0x1024010d },
{ 0x0024, 0x00cb2522 },
{ 0x0038, 0xffffff82 },
{ 0x003C, 0x00000000 },
{ 0x0040, 0x00000000 },
{ 0x0044, 0x00000000 },
{ 0x0048, 0x00000000 },
{ 0x004C, 0x00000000 },
{ 0x0050, 0x00000000 },
{ 0x0054, 0x00000000 },
{ 0x0058, 0x00000000 },
{ 0x005C, 0x00000000 },
{ 0x0060, 0x0f2aa02a },
{ 0x0064, 0x003f3005 },
{ 0x0068, 0x02020202 },
{ 0x0070, 0x00000000 },
{ 0x0074, 0x00000000 },
{ 0x0078, 0x00000000 },
{ 0x007C, 0x00000000 },
{ 0x0034, 0x00000001 },
{ 0xFF00, 0x00000043 },
{ 0x002C, 0x00000942 },
{ 0x0030, 0x00000040 },
{ 0x0028, 0x00000005 },
{ 0x0028, 0x00000007 },
{ 0x0028, 0x00000003 },
{ 0x0028, 0x00000001 },
{ 0x000C, 0x00005a08 },
{ 0x002C, 0x00000842 },
{ 0x0028, 0x00000001 },
{ 0x0030, 0x000003c0 },
{ 0x0028, 0x00000003 },
{ 0x0030, 0x00000040 },
{ 0x0028, 0x00000003 },
{ 0x000C, 0x00005a21 },
{ 0x0034, 0x00007c03 },
{ 0x0120, 0x00005061 },
{ 0xffff, 0xffffffff },
};
static void vInitDRAMReg(ScrnInfoPtr pScrn)
{
AST_DRAMStruct *pjDRAMRegInfo;
ASTRecPtr pAST = ASTPTR(pScrn);
ULONG i, ulTemp, ulData;
UCHAR jReg;
AST2150DRAMParam param;
GetIndexRegMask(CRTC_PORT, 0xD0, 0xFF, jReg);
if ((jReg & 0x80) == 0) /* VGA only */
{
if (pAST->jChipType == AST2000)
{
pjDRAMRegInfo = AST2000DRAMTableData;
*(ULONG *) (pAST->MMIOVirtualAddr + 0xF004) = 0x1e6e0000;
*(ULONG *) (pAST->MMIOVirtualAddr + 0xF000) = 0x1;
*(ULONG *) (pAST->MMIOVirtualAddr + 0x10100) = 0xa8;
do {
;
} while (*(volatile ULONG *) (pAST->MMIOVirtualAddr + 0x10100) != 0xa8);
}
else /* AST2100/1100 */
{
if ((pAST->jChipType == AST2100) || (pAST->jChipType == AST2200))
pjDRAMRegInfo = AST2100DRAMTableData;
else
pjDRAMRegInfo = AST1100DRAMTableData;
*(ULONG *) (pAST->MMIOVirtualAddr + 0xF004) = 0x1e6e0000;
*(ULONG *) (pAST->MMIOVirtualAddr + 0xF000) = 0x1;
*(ULONG *) (pAST->MMIOVirtualAddr + 0x12000) = 0x1688A8A8;
do {
;
} while (*(volatile ULONG *) (pAST->MMIOVirtualAddr + 0x12000) != 0x01);
*(ULONG *) (pAST->MMIOVirtualAddr + 0x10000) = 0xFC600309;
do {
;
} while (*(volatile ULONG *) (pAST->MMIOVirtualAddr + 0x10000) != 0x01);
}
while (pjDRAMRegInfo->Index != 0xFFFF)
{
if (pjDRAMRegInfo->Index == 0xFF00) /* Delay function */
{
for (i=0; i<15; i++)
usleep(pjDRAMRegInfo->Data);
}
else if ( (pjDRAMRegInfo->Index == 0x0004) && (pAST->jChipType != AST2000) )
{
ulData = pjDRAMRegInfo->Data;
if (pAST->jDRAMType == DRAMTYPE_1Gx16)
ulData = 0x00000d89;
else if (pAST->jDRAMType == DRAMTYPE_1Gx32)
ulData = 0x00000c8d;
ulTemp = *(ULONG *) (pAST->MMIOVirtualAddr + 0x12070);
ulTemp &= 0x0000000C;
ulTemp <<= 2;
*(ULONG *) (pAST->MMIOVirtualAddr + 0x10000 + pjDRAMRegInfo->Index) = (ulData | ulTemp);
}
else
{
*(ULONG *) (pAST->MMIOVirtualAddr + 0x10000 + pjDRAMRegInfo->Index) = pjDRAMRegInfo->Data;
}
pjDRAMRegInfo++;
}
/* AST2100/2150 DRAM Calibration, ycchen@021511 */
ulData = *(ULONG *) (pAST->MMIOVirtualAddr + 0x10120);
if (ulData == 0x5061) /* 266MHz */
{
param.pjMMIOVirtualAddress = pAST->MMIOVirtualAddr;
ulData = *(ULONG *) (pAST->MMIOVirtualAddr + 0x10004);
if (ulData & 0x40)
CBRDLLI_AST2150(&param, 16); /* 16bits */
else
CBRDLLI_AST2150(&param, 32); /* 32bits */
}
switch (pAST->jChipType)
{
case AST2000:
*(ULONG *) (pAST->MMIOVirtualAddr + 0x10140) |= 0x40;
break;
case AST1100:
case AST2100:
case AST2200:
case AST2150:
ulTemp = *(ULONG *) (pAST->MMIOVirtualAddr + 0x1200c);
*(ULONG *) (pAST->MMIOVirtualAddr + 0x1200c) = (ulTemp & 0xFFFFFFFD);
*(ULONG *) (pAST->MMIOVirtualAddr + 0x12040) |= 0x40;
break;
}
} /* Init DRAM */
/* wait ready */
do {
GetIndexRegMask(CRTC_PORT, 0xD0, 0xFF, jReg);
} while ((jReg & 0x40) == 0);
} /* vInitDRAMReg */
/*
* AST2300 DRAM settings modules
*/
#define DDR3 0
#define DDR2 1
typedef struct _AST2300DRAMParam {
UCHAR *pjMMIOVirtualAddress;
ULONG DRAM_Type;
ULONG DRAM_ChipID;
ULONG DRAM_Freq;
ULONG VRAM_Size;
ULONG ODT; /* 0/75/150 */
ULONG WODT; /* 0/40/60/120 */
ULONG RODT;
ULONG DRAM_CONFIG;
ULONG REG_PERIOD;
ULONG REG_MADJ;
ULONG REG_SADJ;
ULONG REG_MRS;
ULONG REG_EMRS;
ULONG REG_AC1;
ULONG REG_AC2;
ULONG REG_DQSIC;
ULONG REG_DRV;
ULONG REG_IOZ;
ULONG REG_DQIDLY;
ULONG REG_FREQ;
ULONG MADJ_MAX;
ULONG DLL2_FINETUNE_STEP;
} AST2300DRAMParam, *PAST2300DRAMParam;
/*
* DQSI DLL CBR Setting
*/
#define CBR_SIZE0 ((1 << 10) - 1)
#define CBR_SIZE1 ((4 << 10) - 1)
#define CBR_SIZE2 ((64 << 10) - 1)
#define CBR_PASSNUM 5
#define CBR_PASSNUM2 5
#define CBR_THRESHOLD 10
#define CBR_THRESHOLD2 10
#define TIMEOUT 5000000
#define CBR_PATNUM 8
ULONG pattern[8] ={
0xFF00FF00,
0xCC33CC33,
0xAA55AA55,
0x88778877,
0x92CC4D6E,
0x543D3CDE,
0xF1E843C7,
0x7C61D253};
static int MMCTestBurst(PAST2300DRAMParam param, ULONG datagen)
{
ULONG data, timeout;
UCHAR *mmiobase;
mmiobase = param->pjMMIOVirtualAddress;
MOutdwm(mmiobase, 0x1E6E0070, 0x00000000);
MOutdwm(mmiobase, 0x1E6E0070, 0x000000C1 | (datagen << 3));
timeout = 0;
do{
data = MIndwm(mmiobase, 0x1E6E0070) & 0x3000;
if(data & 0x2000){
return(0);
}
if(++timeout > TIMEOUT){
MOutdwm(mmiobase, 0x1E6E0070, 0x00000000);
return(0);
}
}while(!data);
MOutdwm(mmiobase, 0x1E6E0070, 0x00000000);
return(1);
}
static int MMCTestBurst2(PAST2300DRAMParam param, ULONG datagen)
{
ULONG data, timeout;
UCHAR *mmiobase;
mmiobase = param->pjMMIOVirtualAddress;
MOutdwm(mmiobase, 0x1E6E0070, 0x00000000);
MOutdwm(mmiobase, 0x1E6E0070, 0x00000041 | (datagen << 3));
timeout = 0;
do{
data = MIndwm(mmiobase, 0x1E6E0070) & 0x1000;
if(++timeout > TIMEOUT){
MOutdwm(mmiobase, 0x1E6E0070, 0x00000000);
return(-1);
}
}while(!data);
data = MIndwm(mmiobase, 0x1E6E0078);
data = (data | (data >> 16)) & 0xFFFF;
MOutdwm(mmiobase, 0x1E6E0070, 0x00000000);
return(data);
}
static int MMCTestSingle(PAST2300DRAMParam param, ULONG datagen)
{
ULONG data, timeout;
UCHAR *mmiobase;
mmiobase = param->pjMMIOVirtualAddress;
MOutdwm(mmiobase, 0x1E6E0070, 0x00000000);
MOutdwm(mmiobase, 0x1E6E0070, 0x000000C5 | (datagen << 3));
timeout = 0;
do{
data = MIndwm(mmiobase, 0x1E6E0070) & 0x3000;
if(data & 0x2000){
return(0);
}
if(++timeout > TIMEOUT){
MOutdwm(mmiobase, 0x1E6E0070, 0x00000000);
return(0);
}
}while(!data);
MOutdwm(mmiobase, 0x1E6E0070, 0x00000000);
return(1);
}
static int MMCTestSingle2(PAST2300DRAMParam param, ULONG datagen)
{
ULONG data, timeout;
UCHAR *mmiobase;
mmiobase = param->pjMMIOVirtualAddress;
MOutdwm(mmiobase, 0x1E6E0070, 0x00000000);
MOutdwm(mmiobase, 0x1E6E0070, 0x00000005 | (datagen << 3));
timeout = 0;
do{
data = MIndwm(mmiobase, 0x1E6E0070) & 0x1000;
if(++timeout > TIMEOUT){
MOutdwm(mmiobase, 0x1E6E0070, 0x00000000);
return(-1);
}
}while(!data);
data = MIndwm(mmiobase, 0x1E6E0078);
data = (data | (data >> 16)) & 0xFFFF;
MOutdwm(mmiobase, 0x1E6E0070, 0x00000000);
return(data);
}
static int CBRTest(PAST2300DRAMParam param)
{
ULONG data;
UCHAR *mmiobase;
mmiobase = param->pjMMIOVirtualAddress;
data = MMCTestSingle2(param, 0); if((data & 0xff) && (data & 0xff00)) return(0);
data |= MMCTestBurst2(param, 00); if((data & 0xff) && (data & 0xff00)) return(0);
data |= MMCTestBurst2(param, 01); if((data & 0xff) && (data & 0xff00)) return(0);
data |= MMCTestBurst2(param, 02); if((data & 0xff) && (data & 0xff00)) return(0);
data |= MMCTestBurst2(param, 03); if((data & 0xff) && (data & 0xff00)) return(0);
data |= MMCTestBurst2(param, 04); if((data & 0xff) && (data & 0xff00)) return(0);
data |= MMCTestBurst2(param, 05); if((data & 0xff) && (data & 0xff00)) return(0);
data |= MMCTestBurst2(param, 06); if((data & 0xff) && (data & 0xff00)) return(0);
data |= MMCTestBurst2(param, 07); if((data & 0xff) && (data & 0xff00)) return(0);
if(!data) return(3);
else if(data & 0xff) return(2);
return(1);
}
static int CBRScan(PAST2300DRAMParam param)
{
ULONG data, data2, patcnt, loop;
UCHAR *mmiobase;
mmiobase = param->pjMMIOVirtualAddress;
data2 = 3;
for(patcnt = 0;patcnt < CBR_PATNUM;patcnt++){
MOutdwm(mmiobase, 0x1E6E007C, pattern[patcnt]);
for(loop = 0;loop < CBR_PASSNUM2;loop++){
if((data = CBRTest(param)) != 0){
data2 &= data;
if(!data2){
return(0);
}
break;
}
}
if(loop == CBR_PASSNUM2){
return(0);
}
}
return(data2);
}
static ULONG CBRTest2(PAST2300DRAMParam param)
{
ULONG data;
UCHAR *mmiobase;
mmiobase = param->pjMMIOVirtualAddress;
data = MMCTestBurst2(param, 0); if(data == 0xffff) return(0);
data |= MMCTestSingle2(param, 0); if(data == 0xffff) return(0);
return(~data & 0xffff);
}
static ULONG CBRScan2(PAST2300DRAMParam param)
{
ULONG data, data2, patcnt, loop;
UCHAR *mmiobase;
mmiobase = param->pjMMIOVirtualAddress;
data2 = 0xffff;
for(patcnt = 0;patcnt < CBR_PATNUM;patcnt++){
MOutdwm(mmiobase, 0x1E6E007C, pattern[patcnt]);
for(loop = 0;loop < CBR_PASSNUM2;loop++){
if((data = CBRTest2(param)) != 0){
data2 &= data;
if(!data2){
return(0);
}
break;
}
}
if(loop == CBR_PASSNUM2){
return(0);
}
}
return(data2);
}
static ULONG CBRTest3(PAST2300DRAMParam param)
{
if(!MMCTestBurst(param, 0)) return(0);
if(!MMCTestSingle(param, 0)) return(0);
return(1);
}
static ULONG CBRScan3(PAST2300DRAMParam param)
{
ULONG patcnt, loop;
UCHAR *mmiobase;
mmiobase = param->pjMMIOVirtualAddress;
for(patcnt = 0;patcnt < CBR_PATNUM;patcnt++){
MOutdwm(mmiobase, 0x1E6E007C, pattern[patcnt]);
for(loop = 0;loop < 2;loop++){
if(CBRTest3(param)){
break;
}
}
if(loop == 2){
return(0);
}
}
return(1);
}
static Bool finetuneDQI_L(PAST2300DRAMParam param)
{
ULONG gold_sadj[2], dllmin[16], dllmax[16], dlli, data, cnt, mask, passcnt, retry = 0;
UCHAR *mmiobase;
Bool status = FALSE;
mmiobase = param->pjMMIOVirtualAddress;
FINETUNE_START:
for(cnt = 0;cnt < 16;cnt++){
dllmin[cnt] = 0xff;
dllmax[cnt] = 0x0;
}
passcnt = 0;
for(dlli = 0;dlli < 76;dlli++){
MOutdwm(mmiobase, 0x1E6E0068, 0x00001400 | (dlli << 16) | (dlli << 24));
MOutdwm(mmiobase, 0x1E6E0074, CBR_SIZE1);
data = CBRScan2(param);
if(data != 0){
mask = 0x00010001;
for(cnt = 0;cnt < 16;cnt++){
if(data & mask){
if(dllmin[cnt] > dlli){
dllmin[cnt] = dlli;
}
if(dllmax[cnt] < dlli){
dllmax[cnt] = dlli;
}
}
mask <<= 1;
}
passcnt++;
}else if(passcnt >= CBR_THRESHOLD2){
break;
}
}
gold_sadj[0] = 0x0;
passcnt = 0;
for(cnt = 0;cnt < 16;cnt++){
if((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)){
gold_sadj[0] += dllmin[cnt];
passcnt++;
}
}
if (retry++ > 10)
goto FINETUNE_DONE;
if(passcnt != 16){
goto FINETUNE_START;
}
status = TRUE;
FINETUNE_DONE:
gold_sadj[0] = gold_sadj[0] >> 4;
gold_sadj[1] = gold_sadj[0];
data = 0;
for(cnt = 0;cnt < 8;cnt++){
data >>= 3;
if((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)){
dlli = dllmin[cnt];
if(gold_sadj[0] >= dlli){
dlli = ((gold_sadj[0] - dlli) * 19) >> 5;
if(dlli > 3){
dlli = 3;
}
}else{
dlli = ((dlli - gold_sadj[0]) * 19) >> 5;
if(dlli > 4){
dlli = 4;
}
dlli = (8 - dlli) & 0x7;
}
data |= dlli << 21;
}
}
MOutdwm(mmiobase, 0x1E6E0080, data);
data = 0;
for(cnt = 8;cnt < 16;cnt++){
data >>= 3;
if((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)){
dlli = dllmin[cnt];
if(gold_sadj[1] >= dlli){
dlli = ((gold_sadj[1] - dlli) * 19) >> 5;
if(dlli > 3){
dlli = 3;
}else{
dlli = (dlli - 1) & 0x7;
}
}else{
dlli = ((dlli - gold_sadj[1]) * 19) >> 5;
dlli += 1;
if(dlli > 4){
dlli = 4;
}
dlli = (8 - dlli) & 0x7;
}
data |= dlli << 21;
}
}
MOutdwm(mmiobase, 0x1E6E0084, data);
return status;
} /* finetuneDQI_L */
static void finetuneDQSI(PAST2300DRAMParam param)
{
ULONG dlli, dqsip, dqidly, cnt;
ULONG reg_mcr18, reg_mcr0c, passcnt[2], diff;
ULONG g_dqidly, g_dqsip, g_margin, g_side;
unsigned short pass[32][2][2];
char tag[2][76];
UCHAR *mmiobase;
mmiobase = param->pjMMIOVirtualAddress;
/* Disable DQI CBR */
reg_mcr0c = MIndwm(mmiobase, 0x1E6E000C);
reg_mcr18 = MIndwm(mmiobase, 0x1E6E0018);
reg_mcr18 &= 0x0000ffff;
MOutdwm(mmiobase, 0x1E6E0018, reg_mcr18);
for(dlli = 0;dlli < 76;dlli++){
tag[0][dlli] = 0x0;
tag[1][dlli] = 0x0;
}
for(dqidly = 0;dqidly < 32;dqidly++){
pass[dqidly][0][0] = 0xff;
pass[dqidly][0][1] = 0x0;
pass[dqidly][1][0] = 0xff;
pass[dqidly][1][1] = 0x0;
}
for(dqidly = 0;dqidly < 32;dqidly++){
passcnt[0] = passcnt[1] = 0;
for(dqsip = 0;dqsip < 2;dqsip++){
MOutdwm(mmiobase, 0x1E6E000C, 0);
MOutdwm(mmiobase, 0x1E6E0018, reg_mcr18 | (dqidly << 16) | (dqsip << 23));
MOutdwm(mmiobase, 0x1E6E000C, reg_mcr0c);
for(dlli = 0;dlli < 76;dlli++){
MOutdwm(mmiobase, 0x1E6E0068, 0x00001300 | (dlli << 16) | (dlli << 24));
MOutdwm(mmiobase, 0x1E6E0070, 0);
MOutdwm(mmiobase, 0x1E6E0074, CBR_SIZE0);
if(CBRScan3(param)){
if(dlli == 0){
break;
}
passcnt[dqsip]++;
tag[dqsip][dlli] = 'P';
if(dlli < pass[dqidly][dqsip][0]){
pass[dqidly][dqsip][0] = (USHORT) dlli;
}
if(dlli > pass[dqidly][dqsip][1]){
pass[dqidly][dqsip][1] = (USHORT) dlli;
}
}else if(passcnt[dqsip] >= 5){
break;
}else{
pass[dqidly][dqsip][0] = 0xff;
pass[dqidly][dqsip][1] = 0x0;
}
}
}
if(passcnt[0] == 0 && passcnt[1] == 0){
dqidly++;
}
}
/* Search margin */
g_dqidly = g_dqsip = g_margin = g_side = 0;
for(dqidly = 0;dqidly < 32;dqidly++){
for(dqsip = 0;dqsip < 2;dqsip++){
if(pass[dqidly][dqsip][0] > pass[dqidly][dqsip][1]){
continue;
}
diff = pass[dqidly][dqsip][1] - pass[dqidly][dqsip][0];
if((diff+2) < g_margin){
continue;
}
passcnt[0] = passcnt[1] = 0;
for(dlli = pass[dqidly][dqsip][0];dlli > 0 && tag[dqsip][dlli] != 0;dlli--,passcnt[0]++);
for(dlli = pass[dqidly][dqsip][1];dlli < 76 && tag[dqsip][dlli] != 0;dlli++,passcnt[1]++);
if(passcnt[0] > passcnt[1]){
passcnt[0] = passcnt[1];
}
passcnt[1] = 0;
if(passcnt[0] > g_side){
passcnt[1] = passcnt[0] - g_side;
}
if(diff > (g_margin+1) && (passcnt[1] > 0 || passcnt[0] > 8)){
g_margin = diff;
g_dqidly = dqidly;
g_dqsip = dqsip;
g_side = passcnt[0];
}else if(passcnt[1] > 1 && g_side < 8){
if(diff > g_margin){
g_margin = diff;
}
g_dqidly = dqidly;
g_dqsip = dqsip;
g_side = passcnt[0];
}
}
}
reg_mcr18 = reg_mcr18 | (g_dqidly << 16) | (g_dqsip << 23);
MOutdwm(mmiobase, 0x1E6E0018, reg_mcr18);
} /* finetuneDQSI */
static Bool CBRDLL2(PAST2300DRAMParam param)
{
ULONG dllmin[2], dllmax[2], dlli, data, data2, passcnt, retry=0;
UCHAR *mmiobase;
BOOL status = FALSE;
mmiobase = param->pjMMIOVirtualAddress;
finetuneDQSI(param);
if (finetuneDQI_L(param) == FALSE)
return status;
CBR_START2:
dllmin[0] = dllmin[1] = 0xff;
dllmax[0] = dllmax[1] = 0x0;
passcnt = 0;
for(dlli = 0;dlli < 76;dlli++){
MOutdwm(mmiobase, 0x1E6E0068, 0x00001300 | (dlli << 16) | (dlli << 24));
MOutdwm(mmiobase, 0x1E6E0074, CBR_SIZE2);
data = CBRScan(param);
if(data != 0){
if(data & 0x1){
if(dllmin[0] > dlli){
dllmin[0] = dlli;
}
if(dllmax[0] < dlli){
dllmax[0] = dlli;
}
}
if(data & 0x2){
if(dllmin[1] > dlli){
dllmin[1] = dlli;
}
if(dllmax[1] < dlli){
dllmax[1] = dlli;
}
}
passcnt++;
}else if(passcnt >= CBR_THRESHOLD){
break;
}
}
if (retry++ > 10)
goto CBR_DONE2;
if(dllmax[0] == 0 || (dllmax[0]-dllmin[0]) < CBR_THRESHOLD){
goto CBR_START2;
}
if(dllmax[1] == 0 || (dllmax[1]-dllmin[1]) < CBR_THRESHOLD){
goto CBR_START2;
}
status = TRUE;
CBR_DONE2:
dlli = (dllmin[1] + dllmax[1]) >> 1;
dlli <<= 8;
dlli += (dllmin[0] + dllmax[0]) >> 1;
MOutdwm(mmiobase, 0x1E6E0068, MIndwm(mmiobase, 0x1E720058) | (dlli << 16));
return status;
} /* CBRDLL2 */
static void GetDDR2Info(PAST2300DRAMParam param)
{
UCHAR *mmiobase;
ULONG trap, TRAP_AC2, TRAP_MRS;
mmiobase = param->pjMMIOVirtualAddress;
MOutdwm(mmiobase, 0x1E6E2000, 0x1688A8A8);
/* Ger trap info */
trap = (MIndwm(mmiobase, 0x1E6E2070) >> 25) & 0x3;
TRAP_AC2 = (trap << 20) | (trap << 16);
TRAP_AC2 += 0x00110000;
TRAP_MRS = 0x00000040 | (trap << 4);
param->REG_MADJ = 0x00034C4C;
param->REG_SADJ = 0x00001800;
param->REG_DRV = 0x000000F0;
param->REG_PERIOD = param->DRAM_Freq;
param->RODT = 0;
switch(param->DRAM_Freq){
case 264 : MOutdwm(mmiobase, 0x1E6E2020, 0x0130);
param->WODT = 0;
param->REG_AC1 = 0x11101513;
param->REG_AC2 = 0x78117011;
param->REG_DQSIC = 0x00000092;
param->REG_MRS = 0x00000842;
param->REG_EMRS = 0x00000000;
param->REG_DRV = 0x000000F0;
param->REG_IOZ = 0x00000034;
param->REG_DQIDLY = 0x0000005A;
param->REG_FREQ = 0x00004AC0;
param->MADJ_MAX = 138;
param->DLL2_FINETUNE_STEP = 3;
break;
case 336 : MOutdwm(mmiobase, 0x1E6E2020, 0x0331);
param->WODT = 1;
param->REG_AC1 = 0x22202613;
param->REG_AC2 = 0xAA009016 | TRAP_AC2;
param->REG_DQSIC = 0x000000BA;
param->REG_MRS = 0x00000A02 | TRAP_MRS;
param->REG_EMRS = 0x00000040;
param->REG_DRV = 0x000000FA;
param->REG_IOZ = 0x00000013;
param->REG_DQIDLY = 0x00000074;
param->REG_FREQ = 0x00004DC0;
param->MADJ_MAX = 96;
param->DLL2_FINETUNE_STEP = 3;
switch (param->DRAM_ChipID)
{
case DRAMTYPE_512Mx16:
param->REG_AC2 = 0xAA009012 | TRAP_AC2;
break;
default:
case DRAMTYPE_1Gx16:
param->REG_AC2 = 0xAA009016 | TRAP_AC2;
break;
case DRAMTYPE_2Gx16:
param->REG_AC2 = 0xAA009023 | TRAP_AC2;
break;
case DRAMTYPE_4Gx16:
param->REG_AC2 = 0xAA00903B | TRAP_AC2;
break;
}
break;
default:
case 396 : MOutdwm(mmiobase, 0x1E6E2020, 0x03F1);
param->WODT = 1;
param->RODT = 0;
param->REG_AC1 = 0x33302714;
param->REG_AC2 = 0xCC00B01B | TRAP_AC2;
param->REG_DQSIC = 0x000000E2;
param->REG_MRS = 0x00000C02 | TRAP_MRS;
param->REG_EMRS = 0x00000040;
param->REG_DRV = 0x000000FA;
param->REG_IOZ = 0x00000034;
param->REG_DQIDLY = 0x00000089;
param->REG_FREQ = 0x00005040;
param->MADJ_MAX = 96;
param->DLL2_FINETUNE_STEP = 4;
switch (param->DRAM_ChipID)
{
case DRAMTYPE_512Mx16:
param->REG_AC2 = 0xCC00B016 | TRAP_AC2;
break;
default:
case DRAMTYPE_1Gx16:
param->REG_AC2 = 0xCC00B01B | TRAP_AC2;
break;
case DRAMTYPE_2Gx16:
param->REG_AC2 = 0xCC00B02B | TRAP_AC2;
break;
case DRAMTYPE_4Gx16:
param->REG_AC2 = 0xCC00B03F | TRAP_AC2;
break;
}
break;
case 408 : MOutdwm(mmiobase, 0x1E6E2020, 0x01F0);
param->WODT = 1;
param->RODT = 0;
param->REG_AC1 = 0x33302714;
param->REG_AC2 = 0xCC00B01B | TRAP_AC2;
param->REG_DQSIC = 0x000000E2;
param->REG_MRS = 0x00000C02 | TRAP_MRS;
param->REG_EMRS = 0x00000040;
param->REG_DRV = 0x000000FA;
param->REG_IOZ = 0x00000034;
param->REG_DQIDLY = 0x00000089;
param->REG_FREQ = 0x000050C0;
param->MADJ_MAX = 96;
param->DLL2_FINETUNE_STEP = 4;
switch (param->DRAM_ChipID)
{
case DRAMTYPE_512Mx16:
param->REG_AC2 = 0xCC00B016 | TRAP_AC2;
break;
default:
case DRAMTYPE_1Gx16:
param->REG_AC2 = 0xCC00B01B | TRAP_AC2;
break;
case DRAMTYPE_2Gx16:
param->REG_AC2 = 0xCC00B02B | TRAP_AC2;
break;
case DRAMTYPE_4Gx16:
param->REG_AC2 = 0xCC00B03F | TRAP_AC2;
break;
}
break;
case 456 : MOutdwm(mmiobase, 0x1E6E2020, 0x0230);
param->WODT = 0;
param->REG_AC1 = 0x33302815;
param->REG_AC2 = 0xCD44B01E;
param->REG_DQSIC = 0x000000FC;
param->REG_MRS = 0x00000E72;
param->REG_EMRS = 0x00000000;
param->REG_DRV = 0x00000000;
param->REG_IOZ = 0x00000034;
param->REG_DQIDLY = 0x00000097;
param->REG_FREQ = 0x000052C0;
param->MADJ_MAX = 88;
param->DLL2_FINETUNE_STEP = 3;
break;
case 504 : MOutdwm(mmiobase, 0x1E6E2020, 0x0261);
param->WODT = 1;
param->RODT = 1;
param->REG_AC1 = 0x33302815;
param->REG_AC2 = 0xDE44C022;
param->REG_DQSIC = 0x00000117;
param->REG_MRS = 0x00000E72;
param->REG_EMRS = 0x00000040;
param->REG_DRV = 0x0000000A;
param->REG_IOZ = 0x00000045;
param->REG_DQIDLY = 0x000000A0;
param->REG_FREQ = 0x000054C0;
param->MADJ_MAX = 79;
param->DLL2_FINETUNE_STEP = 3;
break;
case 528 : MOutdwm(mmiobase, 0x1E6E2020, 0x0120);
param->WODT = 1;
param->RODT = 1;
param->REG_AC1 = 0x33302815;
param->REG_AC2 = 0xEF44D024;
param->REG_DQSIC = 0x00000125;
param->REG_MRS = 0x00000E72;
param->REG_EMRS = 0x00000004;
param->REG_DRV = 0x000000F9;
param->REG_IOZ = 0x00000045;
param->REG_DQIDLY = 0x000000A7;
param->REG_FREQ = 0x000055C0;
param->MADJ_MAX = 76;
param->DLL2_FINETUNE_STEP = 3;
break;
case 552 : MOutdwm(mmiobase, 0x1E6E2020, 0x02A1);
param->WODT = 1;
param->RODT = 1;
param->REG_AC1 = 0x43402915;
param->REG_AC2 = 0xFF44E025;
param->REG_DQSIC = 0x00000132;
param->REG_MRS = 0x00000E72;
param->REG_EMRS = 0x00000040;
param->REG_DRV = 0x0000000A;
param->REG_IOZ = 0x00000045;
param->REG_DQIDLY = 0x000000AD;
param->REG_FREQ = 0x000056C0;
param->MADJ_MAX = 76;
param->DLL2_FINETUNE_STEP = 3;
break;
case 576 : MOutdwm(mmiobase, 0x1E6E2020, 0x0140);
param->WODT = 1;
param->RODT = 1;
param->REG_AC1 = 0x43402915;
param->REG_AC2 = 0xFF44E027;
param->REG_DQSIC = 0x0000013F;
param->REG_MRS = 0x00000E72;
param->REG_EMRS = 0x00000004;
param->REG_DRV = 0x000000F5;
param->REG_IOZ = 0x00000045;
param->REG_DQIDLY = 0x000000B3;
param->REG_FREQ = 0x000057C0;
param->MADJ_MAX = 76;
param->DLL2_FINETUNE_STEP = 3;
break;
}
switch (param->DRAM_ChipID)
{
case DRAMTYPE_512Mx16:
param->DRAM_CONFIG = 0x100;
break;
default:
case DRAMTYPE_1Gx16:
param->DRAM_CONFIG = 0x121;
break;
case DRAMTYPE_2Gx16:
param->DRAM_CONFIG = 0x122;
break;
case DRAMTYPE_4Gx16:
param->DRAM_CONFIG = 0x123;
break;
}; /* switch size */
switch (param->VRAM_Size)
{
default:
case VIDEOMEM_SIZE_08M:
param->DRAM_CONFIG |= 0x00;
break;
case VIDEOMEM_SIZE_16M:
param->DRAM_CONFIG |= 0x04;
break;
case VIDEOMEM_SIZE_32M:
param->DRAM_CONFIG |= 0x08;
break;
case VIDEOMEM_SIZE_64M:
param->DRAM_CONFIG |= 0x0c;
break;
}
}
static void GetDDR3Info(PAST2300DRAMParam param)
{
UCHAR *mmiobase;
ULONG trap, TRAP_AC2, TRAP_MRS;
mmiobase = param->pjMMIOVirtualAddress;
MOutdwm(mmiobase, 0x1E6E2000, 0x1688A8A8);
/* Ger trap info */
trap = (MIndwm(mmiobase, 0x1E6E2070) >> 25) & 0x3;
TRAP_AC2 = 0x00020000 + (trap << 16);
TRAP_AC2 |= 0x00300000 +((trap & 0x2) << 19);
TRAP_MRS = 0x00000010 + (trap << 4);
TRAP_MRS |= ((trap & 0x2) << 18);
param->REG_MADJ = 0x00034C4C;
param->REG_SADJ = 0x00001800;
param->REG_DRV = 0x000000F0;
param->REG_PERIOD = param->DRAM_Freq;
param->RODT = 0;
switch(param->DRAM_Freq){
case 336 : MOutdwm(mmiobase, 0x1E6E2020, 0x0331);
param->WODT = 0;
param->REG_AC1 = 0x22202725;
param->REG_AC2 = 0xAA007613 | TRAP_AC2;
param->REG_DQSIC = 0x000000BA;
param->REG_MRS = 0x04001400 | TRAP_MRS;
param->REG_EMRS = 0x00000000;
param->REG_IOZ = 0x00000023;
param->REG_DQIDLY = 0x00000074;
param->REG_FREQ = 0x00004DC0;
param->MADJ_MAX = 96;
param->DLL2_FINETUNE_STEP = 3;
switch (param->DRAM_ChipID)
{
default:
case DRAMTYPE_512Mx16:
case DRAMTYPE_1Gx16:
param->REG_AC2 = 0xAA007613 | TRAP_AC2;
break;
case DRAMTYPE_2Gx16:
param->REG_AC2 = 0xAA00761c | TRAP_AC2;
break;
case DRAMTYPE_4Gx16:
param->REG_AC2 = 0xAA007636 | TRAP_AC2;
break;
}
break;
default:
case 396 : MOutdwm(mmiobase, 0x1E6E2020, 0x03F1);
param->WODT = 1;
param->REG_AC1 = 0x33302825;
param->REG_AC2 = 0xCC009617 | TRAP_AC2;
param->REG_DQSIC = 0x000000E2;
param->REG_MRS = 0x04001600 | TRAP_MRS;
param->REG_EMRS = 0x00000000;
param->REG_IOZ = 0x00000023;
param->REG_DRV = 0x000000FA;
param->REG_DQIDLY = 0x00000089;
param->REG_FREQ = 0x00005040;
param->MADJ_MAX = 96;
param->DLL2_FINETUNE_STEP = 4;
switch (param->DRAM_ChipID)
{
default:
case DRAMTYPE_512Mx16:
case DRAMTYPE_1Gx16:
param->REG_AC2 = 0xCC009617 | TRAP_AC2;
break;
case DRAMTYPE_2Gx16:
param->REG_AC2 = 0xCC009622 | TRAP_AC2;
break;
case DRAMTYPE_4Gx16:
param->REG_AC2 = 0xCC00963F | TRAP_AC2;
break;
}
break;
case 408 : MOutdwm(mmiobase, 0x1E6E2020, 0x01F0);
param->WODT = 1;
param->REG_AC1 = 0x33302825;
param->REG_AC2 = 0xCC009617 | TRAP_AC2;
param->REG_DQSIC = 0x000000E2;
param->REG_MRS = 0x04001600 | TRAP_MRS;
param->REG_EMRS = 0x00000000;
param->REG_IOZ = 0x00000023;
param->REG_DRV = 0x000000FA;
param->REG_DQIDLY = 0x00000089;
param->REG_FREQ = 0x000050C0;
param->MADJ_MAX = 96;
param->DLL2_FINETUNE_STEP = 4;
switch (param->DRAM_ChipID)
{
default:
case DRAMTYPE_512Mx16:
case DRAMTYPE_1Gx16:
param->REG_AC2 = 0xCC009617 | TRAP_AC2;
break;
case DRAMTYPE_2Gx16:
param->REG_AC2 = 0xCC009622 | TRAP_AC2;
break;
case DRAMTYPE_4Gx16:
param->REG_AC2 = 0xCC00963F | TRAP_AC2;
break;
}
break;
case 456 : MOutdwm(mmiobase, 0x1E6E2020, 0x0230);
param->WODT = 0;
param->REG_AC1 = 0x33302926;
param->REG_AC2 = 0xCD44961A;
param->REG_DQSIC = 0x000000FC;
param->REG_MRS = 0x00081830;
param->REG_EMRS = 0x00000000;
param->REG_IOZ = 0x00000045;
param->REG_DQIDLY = 0x00000097;
param->REG_FREQ = 0x000052C0;
param->MADJ_MAX = 88;
param->DLL2_FINETUNE_STEP = 4;
break;
case 504 : MOutdwm(mmiobase, 0x1E6E2020, 0x0270);
param->WODT = 1;
param->REG_AC1 = 0x33302926;
param->REG_AC2 = 0xDE44A61D;
param->REG_DQSIC = 0x00000117;
param->REG_MRS = 0x00081A30;
param->REG_EMRS = 0x00000000;
param->REG_IOZ = 0x070000BB;
param->REG_DQIDLY = 0x000000A0;
param->REG_FREQ = 0x000054C0;
param->MADJ_MAX = 79;
param->DLL2_FINETUNE_STEP = 4;
break;
case 528 : MOutdwm(mmiobase, 0x1E6E2020, 0x0290);
param->WODT = 1;
param->RODT = 1;
param->REG_AC1 = 0x33302926;
param->REG_AC2 = 0xEF44B61E;
param->REG_DQSIC = 0x00000125;
param->REG_MRS = 0x00081A30;
param->REG_EMRS = 0x00000040;
param->REG_DRV = 0x000000F5;
param->REG_IOZ = 0x00000023;
param->REG_DQIDLY = 0x00000088;
param->REG_FREQ = 0x000055C0;
param->MADJ_MAX = 76;
param->DLL2_FINETUNE_STEP = 3;
break;
case 576 : MOutdwm(mmiobase, 0x1E6E2020, 0x0140);
param->REG_MADJ = 0x00136868;
param->REG_SADJ = 0x00004534;
param->WODT = 1;
param->RODT = 1;
param->REG_AC1 = 0x33302A37;
param->REG_AC2 = 0xEF56B61E;
param->REG_DQSIC = 0x0000013F;
param->REG_MRS = 0x00101A50;
param->REG_EMRS = 0x00000040;
param->REG_DRV = 0x000000FA;
param->REG_IOZ = 0x00000023;
param->REG_DQIDLY = 0x00000078;
param->REG_FREQ = 0x000057C0;
param->MADJ_MAX = 136;
param->DLL2_FINETUNE_STEP = 3;
break;
case 600 : MOutdwm(mmiobase, 0x1E6E2020, 0x02E1);
param->REG_MADJ = 0x00136868;
param->REG_SADJ = 0x00004534;
param->WODT = 1;
param->RODT = 1;
param->REG_AC1 = 0x32302A37;
param->REG_AC2 = 0xDF56B61F;
param->REG_DQSIC = 0x0000014D;
param->REG_MRS = 0x00101A50;
param->REG_EMRS = 0x00000004;
param->REG_DRV = 0x000000F5;
param->REG_IOZ = 0x00000023;
param->REG_DQIDLY = 0x00000078;
param->REG_FREQ = 0x000058C0;
param->MADJ_MAX = 132;
param->DLL2_FINETUNE_STEP = 3;
break;
case 624 : MOutdwm(mmiobase, 0x1E6E2020, 0x0160);
param->REG_MADJ = 0x00136868;
param->REG_SADJ = 0x00004534;
param->WODT = 1;
param->RODT = 1;
param->REG_AC1 = 0x32302A37;
param->REG_AC2 = 0xEF56B621;
param->REG_DQSIC = 0x0000015A;
param->REG_MRS = 0x02101A50;
param->REG_EMRS = 0x00000004;
param->REG_DRV = 0x000000F5;
param->REG_IOZ = 0x00000034;
param->REG_DQIDLY = 0x00000078;
param->REG_FREQ = 0x000059C0;
param->MADJ_MAX = 128;
param->DLL2_FINETUNE_STEP = 3;
break;
} /* switch freq */
switch (param->DRAM_ChipID)
{
case DRAMTYPE_512Mx16:
param->DRAM_CONFIG = 0x130;
break;
default:
case DRAMTYPE_1Gx16:
param->DRAM_CONFIG = 0x131;
break;
case DRAMTYPE_2Gx16:
param->DRAM_CONFIG = 0x132;
break;
case DRAMTYPE_4Gx16:
param->DRAM_CONFIG = 0x133;
break;
}; /* switch size */
switch (param->VRAM_Size)
{
default:
case VIDEOMEM_SIZE_08M:
param->DRAM_CONFIG |= 0x00;
break;
case VIDEOMEM_SIZE_16M:
param->DRAM_CONFIG |= 0x04;
break;
case VIDEOMEM_SIZE_32M:
param->DRAM_CONFIG |= 0x08;
break;
case VIDEOMEM_SIZE_64M:
param->DRAM_CONFIG |= 0x0c;
break;
}
}
static void DDR2_Init(PAST2300DRAMParam param)
{
ULONG data, data2, retry = 0;
UCHAR *mmiobase;
mmiobase = param->pjMMIOVirtualAddress;
DDR2_Init_Start:
MOutdwm(mmiobase, 0x1E6E0000, 0xFC600309);
MOutdwm(mmiobase, 0x1E6E0064, 0x00000000);
MOutdwm(mmiobase, 0x1E6E0034, 0x00000000);
MOutdwm(mmiobase, 0x1E6E0018, 0x00000100);
MOutdwm(mmiobase, 0x1E6E0024, 0x00000000);
MOutdwm(mmiobase, 0x1E6E0064, param->REG_MADJ);
MOutdwm(mmiobase, 0x1E6E0068, param->REG_SADJ);
usleep(10);
MOutdwm(mmiobase, 0x1E6E0064, param->REG_MADJ | 0xC0000);
usleep(10);
MOutdwm(mmiobase, 0x1E6E0004, param->DRAM_CONFIG);
MOutdwm(mmiobase, 0x1E6E0008, 0x90040f);
MOutdwm(mmiobase, 0x1E6E0010, param->REG_AC1);
MOutdwm(mmiobase, 0x1E6E0014, param->REG_AC2);
MOutdwm(mmiobase, 0x1E6E0020, param->REG_DQSIC);
MOutdwm(mmiobase, 0x1E6E0080, 0x00000000);
MOutdwm(mmiobase, 0x1E6E0084, 0x00FFFFFF);
MOutdwm(mmiobase, 0x1E6E0088, param->REG_DQIDLY);
MOutdwm(mmiobase, 0x1E6E0018, 0x4000A130);
MOutdwm(mmiobase, 0x1E6E0018, 0x00002330);
MOutdwm(mmiobase, 0x1E6E0038, 0x00000000);
MOutdwm(mmiobase, 0x1E6E0040, 0xFF808000);
MOutdwm(mmiobase, 0x1E6E0044, 0x88848466);
MOutdwm(mmiobase, 0x1E6E0048, 0x44440008);
MOutdwm(mmiobase, 0x1E6E004C, 0x00000000);
MOutdwm(mmiobase, 0x1E6E0050, 0x80000000);
MOutdwm(mmiobase, 0x1E6E0050, 0x00000000);
MOutdwm(mmiobase, 0x1E6E0054, 0);
MOutdwm(mmiobase, 0x1E6E0060, param->REG_DRV);
MOutdwm(mmiobase, 0x1E6E006C, param->REG_IOZ);
MOutdwm(mmiobase, 0x1E6E0070, 0x00000000);
MOutdwm(mmiobase, 0x1E6E0074, 0x00000000);
MOutdwm(mmiobase, 0x1E6E0078, 0x00000000);
MOutdwm(mmiobase, 0x1E6E007C, 0x00000000);
/* Wait MCLK2X lock to MCLK */
do{
data = MIndwm(mmiobase, 0x1E6E001C);
}while(!(data & 0x08000000));
data = MIndwm(mmiobase, 0x1E6E001C);
data = (data >> 8) & 0xff;
while((data & 0x08) || ((data & 0x7) < 2) || (data < 4)){
data2 = (MIndwm(mmiobase, 0x1E6E0064) & 0xfff3ffff) + 4;
if((data2 & 0xff) > param->MADJ_MAX){
break;
}
MOutdwm(mmiobase, 0x1E6E0064, data2);
if(data2 & 0x00100000){
data2 = ((data2 & 0xff) >> 3) + 3;
}else{
data2 = ((data2 & 0xff) >> 2) + 5;
}
data = MIndwm(mmiobase, 0x1E6E0068) & 0xffff00ff;
data2 += data & 0xff;
data = data | (data2 << 8);
MOutdwm(mmiobase, 0x1E6E0068, data);
usleep(10);
MOutdwm(mmiobase, 0x1E6E0064, MIndwm(mmiobase, 0x1E6E0064) | 0xC0000);
usleep(10);
data = MIndwm(mmiobase, 0x1E6E0018) & 0xfffff1ff;
MOutdwm(mmiobase, 0x1E6E0018, data);
data = data | 0x200;
MOutdwm(mmiobase, 0x1E6E0018, data);
do{
data = MIndwm(mmiobase, 0x1E6E001C);
}while(!(data & 0x08000000));
data = MIndwm(mmiobase, 0x1E6E001C);
data = (data >> 8) & 0xff;
}
MOutdwm(mmiobase, 0x1E720058, MIndwm(mmiobase, 0x1E6E0068) & 0xffff);
data = MIndwm(mmiobase, 0x1E6E0018) | 0xC00;
MOutdwm(mmiobase, 0x1E6E0018, data);
MOutdwm(mmiobase, 0x1E6E0034, 0x00000001);
MOutdwm(mmiobase, 0x1E6E000C, 0x00000000);
usleep(50);
/* Mode Register Setting */
MOutdwm(mmiobase, 0x1E6E002C, param->REG_MRS | 0x100);
MOutdwm(mmiobase, 0x1E6E0030, param->REG_EMRS);
MOutdwm(mmiobase, 0x1E6E0028, 0x00000005);
MOutdwm(mmiobase, 0x1E6E0028, 0x00000007);
MOutdwm(mmiobase, 0x1E6E0028, 0x00000003);
MOutdwm(mmiobase, 0x1E6E0028, 0x00000001);
MOutdwm(mmiobase, 0x1E6E000C, 0x00005C08);
MOutdwm(mmiobase, 0x1E6E002C, param->REG_MRS);
MOutdwm(mmiobase, 0x1E6E0028, 0x00000001);
MOutdwm(mmiobase, 0x1E6E0030, param->REG_EMRS | 0x380);
MOutdwm(mmiobase, 0x1E6E0028, 0x00000003);
MOutdwm(mmiobase, 0x1E6E0030, param->REG_EMRS);
MOutdwm(mmiobase, 0x1E6E0028, 0x00000003);
MOutdwm(mmiobase, 0x1E6E000C, 0x7FFF5C01);
data = 0;
if(param->WODT){
data = 0x500;
}
if(param->RODT){
data = data | 0x3000 | ((param->REG_AC2 & 0x60000) >> 3);
}
MOutdwm(mmiobase, 0x1E6E0034, data | 0x3);
MOutdwm(mmiobase, 0x1E6E0120, param->REG_FREQ);
/* Calibrate the DQSI delay */
if ((CBRDLL2(param)==FALSE) && (retry++ < 10))
goto DDR2_Init_Start;
/* ECC Memory Initialization */
#ifdef ECC
MOutdwm(mmiobase, 0x1E6E007C, 0x00000000);
MOutdwm(mmiobase, 0x1E6E0070, 0x221);
do{
data = MIndwm(mmiobase, 0x1E6E0070);
}while(!(data & 0x00001000));
MOutdwm(mmiobase, 0x1E6E0070, 0x00000000);
MOutdwm(mmiobase, 0x1E6E0050, 0x80000000);
MOutdwm(mmiobase, 0x1E6E0050, 0x00000000);
#endif
}
static void DDR3_Init(PAST2300DRAMParam param)
{
ULONG data, data2, retry = 0;
UCHAR *mmiobase;
mmiobase = param->pjMMIOVirtualAddress;
DDR3_Init_Start:
MOutdwm(mmiobase, 0x1E6E0000, 0xFC600309);
MOutdwm(mmiobase, 0x1E6E0064, 0x00000000);
MOutdwm(mmiobase, 0x1E6E0034, 0x00000000);
MOutdwm(mmiobase, 0x1E6E0018, 0x00000100);
MOutdwm(mmiobase, 0x1E6E0024, 0x00000000);
usleep(10);
MOutdwm(mmiobase, 0x1E6E0064, param->REG_MADJ);
MOutdwm(mmiobase, 0x1E6E0068, param->REG_SADJ);
usleep(10);
MOutdwm(mmiobase, 0x1E6E0064, param->REG_MADJ | 0xC0000);
usleep(10);
MOutdwm(mmiobase, 0x1E6E0004, param->DRAM_CONFIG);
MOutdwm(mmiobase, 0x1E6E0008, 0x90040f);
MOutdwm(mmiobase, 0x1E6E0010, param->REG_AC1);
MOutdwm(mmiobase, 0x1E6E0014, param->REG_AC2);
MOutdwm(mmiobase, 0x1E6E0020, param->REG_DQSIC);
MOutdwm(mmiobase, 0x1E6E0080, 0x00000000);
MOutdwm(mmiobase, 0x1E6E0084, 0x00FFFFFF);
MOutdwm(mmiobase, 0x1E6E0088, param->REG_DQIDLY);
MOutdwm(mmiobase, 0x1E6E0018, 0x4000A170);
MOutdwm(mmiobase, 0x1E6E0018, 0x00002370);
MOutdwm(mmiobase, 0x1E6E0038, 0x00000000);
MOutdwm(mmiobase, 0x1E6E0040, 0xFF444444);
MOutdwm(mmiobase, 0x1E6E0044, 0x22222222);
MOutdwm(mmiobase, 0x1E6E0048, 0x22222222);
MOutdwm(mmiobase, 0x1E6E004C, 0x00000002);
MOutdwm(mmiobase, 0x1E6E0050, 0x80000000);
MOutdwm(mmiobase, 0x1E6E0050, 0x00000000);
MOutdwm(mmiobase, 0x1E6E0054, 0);
MOutdwm(mmiobase, 0x1E6E0060, param->REG_DRV);
MOutdwm(mmiobase, 0x1E6E006C, param->REG_IOZ);
MOutdwm(mmiobase, 0x1E6E0070, 0x00000000);
MOutdwm(mmiobase, 0x1E6E0074, 0x00000000);
MOutdwm(mmiobase, 0x1E6E0078, 0x00000000);
MOutdwm(mmiobase, 0x1E6E007C, 0x00000000);
/* Wait MCLK2X lock to MCLK */
do{
data = MIndwm(mmiobase, 0x1E6E001C);
}while(!(data & 0x08000000));
data = MIndwm(mmiobase, 0x1E6E001C);
data = (data >> 8) & 0xff;
while((data & 0x08) || ((data & 0x7) < 2) || (data < 4)){
data2 = (MIndwm(mmiobase, 0x1E6E0064) & 0xfff3ffff) + 4;
if((data2 & 0xff) > param->MADJ_MAX){
break;
}
MOutdwm(mmiobase, 0x1E6E0064, data2);
if(data2 & 0x00100000){
data2 = ((data2 & 0xff) >> 3) + 3;
}else{
data2 = ((data2 & 0xff) >> 2) + 5;
}
data = MIndwm(mmiobase, 0x1E6E0068) & 0xffff00ff;
data2 += data & 0xff;
data = data | (data2 << 8);
MOutdwm(mmiobase, 0x1E6E0068, data);
usleep(10);
MOutdwm(mmiobase, 0x1E6E0064, MIndwm(mmiobase, 0x1E6E0064) | 0xC0000);
usleep(10);
data = MIndwm(mmiobase, 0x1E6E0018) & 0xfffff1ff;
MOutdwm(mmiobase, 0x1E6E0018, data);
data = data | 0x200;
MOutdwm(mmiobase, 0x1E6E0018, data);
do{
data = MIndwm(mmiobase, 0x1E6E001C);
}while(!(data & 0x08000000));
data = MIndwm(mmiobase, 0x1E6E001C);
data = (data >> 8) & 0xff;
}
MOutdwm(mmiobase, 0x1E720058, MIndwm(mmiobase, 0x1E6E0068) & 0xffff);
data = MIndwm(mmiobase, 0x1E6E0018) | 0xC00;
MOutdwm(mmiobase, 0x1E6E0018, data);
MOutdwm(mmiobase, 0x1E6E0034, 0x00000001);
MOutdwm(mmiobase, 0x1E6E000C, 0x00000040);
usleep(50);
/* Mode Register Setting */
MOutdwm(mmiobase, 0x1E6E002C, param->REG_MRS | 0x100);
MOutdwm(mmiobase, 0x1E6E0030, param->REG_EMRS);
MOutdwm(mmiobase, 0x1E6E0028, 0x00000005);
MOutdwm(mmiobase, 0x1E6E0028, 0x00000007);
MOutdwm(mmiobase, 0x1E6E0028, 0x00000003);
MOutdwm(mmiobase, 0x1E6E0028, 0x00000001);
MOutdwm(mmiobase, 0x1E6E002C, param->REG_MRS);
MOutdwm(mmiobase, 0x1E6E000C, 0x00005C08);
MOutdwm(mmiobase, 0x1E6E0028, 0x00000001);
MOutdwm(mmiobase, 0x1E6E000C, 0x00005C01);
data = 0;
if(param->WODT){
data = 0x300;
}
if(param->RODT){
data = data | 0x3000 | ((param->REG_AC2 & 0x60000) >> 3);
}
MOutdwm(mmiobase, 0x1E6E0034, data | 0x3);
/* Calibrate the DQSI delay */
if ((CBRDLL2(param)==FALSE) && (retry++ < 10))
goto DDR3_Init_Start;
MOutdwm(mmiobase, 0x1E6E0120, param->REG_FREQ);
/* ECC Memory Initialization */
#ifdef ECC
MOutdwm(mmiobase, 0x1E6E007C, 0x00000000);
MOutdwm(mmiobase, 0x1E6E0070, 0x221);
do{
data = MIndwm(mmiobase, 0x1E6E0070);
}while(!(data & 0x00001000));
MOutdwm(mmiobase, 0x1E6E0070, 0x00000000);
MOutdwm(mmiobase, 0x1E6E0050, 0x80000000);
MOutdwm(mmiobase, 0x1E6E0050, 0x00000000);
#endif
}
static void vInitAST2300DRAMReg(ScrnInfoPtr pScrn)
{
ASTRecPtr pAST = ASTPTR(pScrn);
AST2300DRAMParam param;
ULONG i, ulTemp;
UCHAR jReg;
GetIndexRegMask(CRTC_PORT, 0xD0, 0xFF, jReg);
if ((jReg & 0x80) == 0) /* VGA only */
{
*(ULONG *) (pAST->MMIOVirtualAddr + 0xF004) = 0x1e6e0000;
*(ULONG *) (pAST->MMIOVirtualAddr + 0xF000) = 0x1;
*(ULONG *) (pAST->MMIOVirtualAddr + 0x12000) = 0x1688A8A8;
do {
;
} while (*(volatile ULONG *) (pAST->MMIOVirtualAddr + 0x12000) != 0x01);
*(ULONG *) (pAST->MMIOVirtualAddr + 0x10000) = 0xFC600309;
do {
;
} while (*(volatile ULONG *) (pAST->MMIOVirtualAddr + 0x10000) != 0x01);
/* Slow down CPU/AHB CLK in VGA only mode */
ulTemp = *(ULONG *) (pAST->MMIOVirtualAddr + 0x12008);
ulTemp |= 0x73;
*(ULONG *) (pAST->MMIOVirtualAddr + 0x12008) = ulTemp;
param.pjMMIOVirtualAddress = pAST->MMIOVirtualAddr;
param.DRAM_Type = DDR3; /* DDR3 */
ulTemp = MIndwm(param.pjMMIOVirtualAddress, 0x1E6E2070);
if (ulTemp & 0x01000000)
param.DRAM_Type = DDR2; /* DDR2 */
param.DRAM_ChipID = (ULONG) pAST->jDRAMType;
param.DRAM_Freq = pAST->ulMCLK;
param.VRAM_Size = pAST->ulVRAMSize;
if (param.DRAM_Type == DDR3)
{
GetDDR3Info(&param);
DDR3_Init(&param);
}
else
{
GetDDR2Info(&param);
DDR2_Init(&param);
}
ulTemp = MIndwm(param.pjMMIOVirtualAddress, 0x1E6E2040);
MOutdwm(param.pjMMIOVirtualAddress, 0x1E6E2040, ulTemp | 0x40);
}
/* wait ready */
do {
GetIndexRegMask(CRTC_PORT, 0xD0, 0xFF, jReg);
} while ((jReg & 0x40) == 0);
} /* vInitAST2300DRAMReg */
void static vGetDefaultSettings(ScrnInfoPtr pScrn)
{
ASTRecPtr pAST = ASTPTR(pScrn);
ULONG ulData;
if ((pAST->jChipType == AST2300) || (pAST->jChipType == AST2400))
{
*(ULONG *) (pAST->MMIOVirtualAddr + 0xF004) = 0x1e6e0000;
*(ULONG *) (pAST->MMIOVirtualAddr + 0xF000) = 0x1;
ulData = *(ULONG *) (pAST->MMIOVirtualAddr + 0x12070);
switch (ulData & 0x18000000)
{
case 0x00000000:
pAST->jDRAMType = DRAMTYPE_512Mx16;
break;
case 0x08000000:
pAST->jDRAMType = DRAMTYPE_1Gx16;
break;
case 0x10000000:
pAST->jDRAMType = DRAMTYPE_2Gx16;
break;
case 0x18000000:
pAST->jDRAMType = DRAMTYPE_4Gx16;
break;
}
}
else if ((pAST->jChipType == AST2100) || (pAST->jChipType == AST2200))
{
pAST->jDRAMType = DRAMTYPE_512Mx32;
}
else if ((pAST->jChipType == AST1100) || (pAST->jChipType == AST2150))
{
pAST->jDRAMType = DRAMTYPE_1Gx16;
}
} /* vGetDefaultSettings */
static Bool InitDVO(ScrnInfoPtr pScrn)
{
ASTRecPtr pAST = ASTPTR(pScrn);
ULONG ulData;
UCHAR jReg;
*(ULONG *) (pAST->MMIOVirtualAddr + 0xF004) = 0x1e6e0000;
*(ULONG *) (pAST->MMIOVirtualAddr + 0xF000) = 0x1;
*(ULONG *) (pAST->MMIOVirtualAddr + 0x12000) = 0x1688A8A8;
GetIndexRegMask(CRTC_PORT, 0xD0, 0xFF, jReg);
if (!(jReg & 0x80)) /* Init SCU DVO Settings */
{
ulData = *(ULONG *) (pAST->MMIOVirtualAddr + 0x12008); /* delay phase */
ulData &= 0xfffff8ff;
ulData |= 0x00000500;
*(ULONG *) (pAST->MMIOVirtualAddr + 0x12008) = ulData;
if (pAST->jChipType == AST2300)
{
ulData = *(ULONG *) (pAST->MMIOVirtualAddr + 0x12084); /* multi-pins for DVO single-edge */
ulData |= 0xfffe0000;
*(ULONG *) (pAST->MMIOVirtualAddr + 0x12084) = ulData;
ulData = *(ULONG *) (pAST->MMIOVirtualAddr + 0x12088); /* multi-pins for DVO single-edge */
ulData |= 0x000fffff;
*(ULONG *) (pAST->MMIOVirtualAddr + 0x12088) = ulData;
ulData = *(ULONG *) (pAST->MMIOVirtualAddr + 0x12090); /* multi-pins for DVO single-edge */
ulData &= 0xffffffcf;
ulData |= 0x00000020;
*(ULONG *) (pAST->MMIOVirtualAddr + 0x12090) = ulData;
}
else /* AST2400 */
{
ulData = *(ULONG *) (pAST->MMIOVirtualAddr + 0x12088); /* multi-pins for DVO single-edge */
ulData |= 0x30000000;
*(ULONG *) (pAST->MMIOVirtualAddr + 0x12088) = ulData;
ulData = *(ULONG *) (pAST->MMIOVirtualAddr + 0x1208c); /* multi-pins for DVO single-edge */
ulData |= 0x000000cf;
*(ULONG *) (pAST->MMIOVirtualAddr + 0x1208c) = ulData;
ulData = *(ULONG *) (pAST->MMIOVirtualAddr + 0x120a4); /* multi-pins for DVO single-edge */
ulData |= 0xffff0000;
*(ULONG *) (pAST->MMIOVirtualAddr + 0x120a4) = ulData;
ulData = *(ULONG *) (pAST->MMIOVirtualAddr + 0x120a8); /* multi-pins for DVO single-edge */
ulData |= 0x0000000f;
*(ULONG *) (pAST->MMIOVirtualAddr + 0x120a8) = ulData;
ulData = *(ULONG *) (pAST->MMIOVirtualAddr + 0x12094); /* multi-pins for DVO single-edge */
ulData |= 0x00000002;
*(ULONG *) (pAST->MMIOVirtualAddr + 0x12094) = ulData;
}
}
/* Force to DVO */
ulData = *(ULONG *) (pAST->MMIOVirtualAddr + 0x1202c);
ulData &= 0xfffbffff;
*(ULONG *) (pAST->MMIOVirtualAddr + 0x1202c) = ulData;
/* Init VGA DVO Settings */
SetIndexRegMask(CRTC_PORT, 0xA3, 0xCF, 0x80); /* enable DVO, single-edge */
return TRUE;
} /* InitDVO */
static void vInit3rdTX(ScrnInfoPtr pScrn)
{
ASTRecPtr pAST = ASTPTR(pScrn);
ULONG ulData;
UCHAR jReg;
/* Only support on AST2300/2400 */
if ((pAST->jChipType == AST2300) || (pAST->jChipType == AST2400))
{
GetIndexRegMask(CRTC_PORT, 0xD1, 0xFF, jReg); /* D[1]: DVO Enable */
switch (jReg & 0x0E) /* D[11:9] */
{
case 0x04: /* Sil164 */
InitDVO(pScrn);
break;
case 0x08: /* DP501 with VBIOS launch FW */
LaunchM68K(pScrn);
case 0x0C: /* DP501 with BMC launch FW */
InitDVO(pScrn);
break;
default: /* Force to VGA */
if (pAST->jTxChipType == Tx_Sil164)
InitDVO(pScrn);
else
{
*(ULONG *)(pAST->MMIOVirtualAddr + 0x12000) = 0x1688A8A8;
ulData = *(ULONG *) (pAST->MMIOVirtualAddr + 0x1202c);
ulData &= 0xfffcffff;
*(ULONG *)(pAST->MMIOVirtualAddr) = ulData;
}
}
}
} /* vInit3rdTX */
/*
* Flags: 0: POST init
* 1: resume from power management
*/
Bool ASTInitVGA(ScrnInfoPtr pScrn, ULONG Flags)
{
ASTRecPtr pAST;
uint32_t ulData;
pAST = ASTPTR(pScrn);
{
/* Enable PCI */
PCI_READ_LONG(pAST->PciInfo, &ulData, 0x04);
ulData |= 0x03;
PCI_WRITE_LONG(pAST->PciInfo, ulData, 0x04);
/* Enable VGA */
vEnableVGA(pScrn);
vASTOpenKey(pScrn);
vSetDefExtReg(pScrn);
if (Flags == 0)
vGetDefaultSettings(pScrn);
if ((pAST->jChipType == AST2300) || (pAST->jChipType == AST2400))
vInitAST2300DRAMReg(pScrn);
else
vInitDRAMReg(pScrn);
vInit3rdTX(pScrn);
}
return (TRUE);
} /* Init VGA */
/* Get EDID */
void
I2CWriteClock(ASTRecPtr pAST, UCHAR data)
{
UCHAR ujCRB7, jtemp;
ULONG i;
for (i=0;i<0x10000; i++)
{
ujCRB7 = ((data & 0x01) ? 0:1); /* low active */
SetIndexRegMask(CRTC_PORT, 0xB7, 0xFE, ujCRB7);
GetIndexRegMask(CRTC_PORT, 0xB7, 0x01, jtemp);
if (ujCRB7 == jtemp) break;
}
}
void
I2CWriteData(ASTRecPtr pAST, UCHAR data)
{
UCHAR volatile ujCRB7, jtemp;
ULONG i;
for (i=0;i<0x1000; i++)
{
ujCRB7 = ((data & 0x01) ? 0:1) << 2; /* low active */
SetIndexRegMask(CRTC_PORT, 0xB7, 0xFB, ujCRB7);
GetIndexRegMask(CRTC_PORT, 0xB7, 0x04, jtemp);
if (ujCRB7 == jtemp) break;
}
}
Bool
I2CReadClock(ASTRecPtr pAST)
{
UCHAR volatile ujCRB7;
GetIndexRegMask(CRTC_PORT, 0xB7, 0x10, ujCRB7);
ujCRB7 >>= 4;
return ((ujCRB7 & 0x01) ? 1:0);
}
Bool
I2CReadData(ASTRecPtr pAST)
{
UCHAR volatile ujCRB7;
GetIndexRegMask(CRTC_PORT, 0xB7, 0x20, ujCRB7);
ujCRB7 >>= 5;
return ((ujCRB7 & 0x01) ? 1:0);
}
void
I2CDelay(ASTRecPtr pAST)
{
ULONG i;
UCHAR jtemp;
for (i=0;i<150;i++)
jtemp = GetReg(SEQ_PORT);
}
void
I2CStart(ASTRecPtr pAST)
{
I2CWriteClock(pAST, 0x00); /* Set Clk Low */
I2CDelay(pAST);
I2CWriteData(pAST, 0x01); /* Set Data High */
I2CDelay(pAST);
I2CWriteClock(pAST, 0x01); /* Set Clk High */
I2CDelay(pAST);
I2CWriteData(pAST, 0x00); /* Set Data Low */
I2CDelay(pAST);
I2CWriteClock(pAST, 0x01); /* Set Clk High */
I2CDelay(pAST);
}
void
I2CStop(ASTRecPtr pAST)
{
I2CWriteClock(pAST, 0x00); /* Set Clk Low */
I2CDelay(pAST);
I2CWriteData(pAST, 0x00); /* Set Data Low */
I2CDelay(pAST);
I2CWriteClock(pAST, 0x01); /* Set Clk High */
I2CDelay(pAST);
I2CWriteData(pAST, 0x01); /* Set Data High */
I2CDelay(pAST);
I2CWriteClock(pAST, 0x01); /* Set Clk High */
I2CDelay(pAST);
}
Bool
CheckACK(ASTRecPtr pAST)
{
UCHAR Data;
I2CWriteClock(pAST, 0x00); /* Set Clk Low */
I2CDelay(pAST);
I2CWriteData(pAST, 0x01); /* Set Data High */
I2CDelay(pAST);
I2CWriteClock(pAST, 0x01); /* Set Clk High */
I2CDelay(pAST);
Data = (UCHAR) I2CReadData(pAST); /* Set Data High */
return ((Data & 0x01) ? 0:1);
}
void
SendACK(ASTRecPtr pAST)
{
I2CWriteClock(pAST, 0x00); /* Set Clk Low */
I2CDelay(pAST);
I2CWriteData(pAST, 0x00); /* Set Data low */
I2CDelay(pAST);
I2CWriteClock(pAST, 0x01); /* Set Clk High */
I2CDelay(pAST);
}
void
SendNACK(ASTRecPtr pAST)
{
I2CWriteClock(pAST, 0x00); /* Set Clk Low */
I2CDelay(pAST);
I2CWriteData(pAST, 0x01); /* Set Data high */
I2CDelay(pAST);
I2CWriteClock(pAST, 0x01); /* Set Clk High */
I2CDelay(pAST);
}
void
SendI2CDataByte(ASTRecPtr pAST, UCHAR data)
{
UCHAR jData;
LONG i;
for (i=7;i>=0;i--)
{
I2CWriteClock(pAST, 0x00); /* Set Clk Low */
I2CDelay(pAST);
jData = ((data >> i) & 0x01) ? 1:0;
I2CWriteData(pAST, jData); /* Set Data Low */
I2CDelay(pAST);
I2CWriteClock(pAST, 0x01); /* Set Clk High */
I2CDelay(pAST);
}
}
UCHAR
ReceiveI2CDataByte(ASTRecPtr pAST)
{
UCHAR jData=0, jTempData;
LONG i, j;
for (i=7;i>=0;i--)
{
I2CWriteClock(pAST, 0x00); /* Set Clk Low */
I2CDelay(pAST);
I2CWriteData(pAST, 0x01); /* Set Data High */
I2CDelay(pAST);
I2CWriteClock(pAST, 0x01); /* Set Clk High */
I2CDelay(pAST);
for (j=0; j<0x1000; j++)
{
if (I2CReadClock(pAST)) break;
}
jTempData = I2CReadData(pAST);
jData |= ((jTempData & 0x01) << i);
I2CWriteClock(pAST, 0x0); /* Set Clk Low */
I2CDelay(pAST);
}
return ((UCHAR)jData);
}
Bool
ASTGetVGAEDID(ScrnInfoPtr pScrn, unsigned char *pEDIDBuffer)
{
ASTRecPtr pAST;
UCHAR *pjDstEDID;
UCHAR jData;
ULONG i;
pAST = ASTPTR(pScrn);
pjDstEDID = (UCHAR *) pEDIDBuffer;
/* Force to DDC2 */
I2CWriteClock(pAST, 0x01); /* Set Clk High */
I2CDelay(pAST);
I2CWriteClock(pAST, 0x00); /* Set Clk Low */
I2CDelay(pAST);
I2CWriteClock(pAST, 0x01); /* Set Clk High */
I2CDelay(pAST);
/* Validate SCL */
if (I2CReadClock(pAST) == 0) /* chk SCL failed */
{
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[GetVGAEDID] Check SCL Failed \n");
return (FALSE);
}
I2CStart(pAST);
SendI2CDataByte(pAST, 0xA0);
if (!CheckACK(pAST))
{
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[GetVGAEDID] Check ACK Failed \n");
return (FALSE);
}
SendI2CDataByte(pAST, 0x00);
if (!CheckACK(pAST))
{
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[GetVGAEDID] Check ACK Failed \n");
return (FALSE);
}
I2CStart(pAST);
SendI2CDataByte(pAST, 0xA1);
if (!CheckACK(pAST))
{
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[GetVGAEDID] Check ACK Failed \n");
return (FALSE);
}
for (i=0; i<127; i++)
{
jData = ReceiveI2CDataByte(pAST);
SendACK(pAST);
*pjDstEDID++ = jData;
}
jData = ReceiveI2CDataByte(pAST);
SendNACK(pAST);
*pjDstEDID = jData;
I2CStop(pAST);
return (TRUE);
} /* ASTGetVGAEDID */
Bool bASTInitAST1180(ScrnInfoPtr pScrn)
{
ASTRecPtr pAST;
uint32_t ulData;
pAST = ASTPTR(pScrn);
/* Enable PCI */
PCI_READ_LONG(pAST->PciInfo, &ulData, 0x04);
ulData |= 0x03;
PCI_WRITE_LONG(pAST->PciInfo, ulData, 0x04);
/* init DRAM if no F/W */
/* TODO */
WriteAST1180SOC(AST1180_MMC_BASE+0x00, 0xFC600309); /* unlock */
WriteAST1180SOC(AST1180_SCU_BASE+0x00, 0x1688a8a8); /* unlock */
usleep(100);
WriteAST1180SOC(AST1180_MMC_BASE+0x08, 0x000011e3); /* req. */
/* init SCU */
#if 0
ReadAST1180SOC(AST1180_SCU_BASE+0x08, ulData); /* delay compensation */
ulData &= 0xFFFFE0FF;
ulData |= 0x00000C00;
WriteAST1180SOC(AST1180_SCU_BASE+0x08, ulData);
#endif
ReadAST1180SOC(AST1180_SCU_BASE+0x0c, ulData); /* 2d clk */
ulData &= 0xFFFFFFFD;
WriteAST1180SOC(AST1180_SCU_BASE+0x0c, ulData);
return (TRUE);
} /* bASTInitAST1180 */
void ASTGetAST1180DRAMInfo(ScrnInfoPtr pScrn)
{
ASTRecPtr pAST = ASTPTR(pScrn);
ULONG ulData;
WriteAST1180SOC(AST1180_MMC_BASE+0x00, 0xFC600309); /* unlock */
ReadAST1180SOC(AST1180_MMC_BASE+0x04, ulData);
pAST->ulDRAMBusWidth = 32;
if (ulData & 0x40)
pAST->ulDRAMBusWidth = 16;
/* DRAM size */
switch (ulData & 0x0C)
{
case 0x00:
pAST->ulDRAMSize = DRAM_SIZE_032M;
break;
case 0x04:
pAST->ulDRAMSize = DRAM_SIZE_064M;
break;
case 0x08:
pAST->ulDRAMSize = DRAM_SIZE_128M;
break;
case 0x0c:
pAST->ulDRAMSize = DRAM_SIZE_256M;
break;
}
/* Get framebuffer size */
switch (ulData & 0x30)
{
case 0x00:
pAST->ulVRAMSize = DRAM_SIZE_016M;
break;
case 0x10:
pAST->ulVRAMSize = DRAM_SIZE_032M;
break;
case 0x20:
pAST->ulVRAMSize = DRAM_SIZE_064M;
break;
case 0x30:
pAST->ulVRAMSize = DRAM_SIZE_128M;
break;
}
/* VRAM base */
if (pAST->ulVRAMSize >= pAST->ulDRAMSize)
pAST->ulVRAMSize = pAST->ulDRAMSize;
pAST->ulVRAMBase = pAST->ulDRAMSize - pAST->ulVRAMSize;
/* MCLK */
pAST->ulMCLK = 200;
} /* ASTGetAST1180DRAMInfo */
void vASTEnableVGAMMIO(ScrnInfoPtr pScrn)
{
ASTRecPtr pAST = ASTPTR(pScrn);
ULONG ulData;
UCHAR jReg;
jReg = inb(pAST->RelocateIO + 0x43);
if (jReg != 0x01)
{
/* Enable PCI */
PCI_READ_LONG(pAST->PciInfo, &ulData, 0x04);
ulData |= 0x03;
PCI_WRITE_LONG(pAST->PciInfo, ulData, 0x04);
outb(pAST->RelocateIO + 0x43, 0x01);
outb(pAST->RelocateIO + 0x42, 0x01);
}
jReg = GetReg(VGA_ENABLE_PORT);
if (jReg == 0xFF) /* MMIO Access is disabled */
{
outw(pAST->RelocateIO + 0x54, 0xa880);
outw(pAST->RelocateIO + 0x54, 0x04a1);
}
} /* vEnableASTVGAMMIO */