3469 lines
95 KiB
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(¶m, 16); /* 16bits */
|
|
else
|
|
CBRDLLI_AST2150(¶m, 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(¶m);
|
|
DDR3_Init(¶m);
|
|
}
|
|
else
|
|
{
|
|
GetDDR2Info(¶m);
|
|
DDR2_Init(¶m);
|
|
}
|
|
|
|
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 */
|