kolibrios-fun/programs/system/drivers/ati2d/init.c
Sergey Semyonov (Serge) a97b422321 pixlib 0.2
git-svn-id: svn://kolibrios.org@881 a494cfbc-eb01-0410-851d-a64ba20cac60
2008-10-19 15:53:12 +00:00

623 lines
20 KiB
C

static Bool rhdMapMMIO(RHDPtr rhdPtr)
{
rhdPtr->MMIOMapSize = 1 << rhdPtr->memsize[RHD_MMIO_BAR];
rhdPtr->MMIOBase = MapIoMem((void*)rhdPtr->memBase[RHD_MMIO_BAR],
rhdPtr->MMIOMapSize,PG_SW+PG_NOCACHE);
if( rhdPtr->MMIOBase==0)
return 0;
DBG(dbgprintf("Mapped IO at %x (size %x)\n", rhdPtr->MMIOBase, rhdPtr->MMIOMapSize));
return 1;
}
/* Read MC register */
unsigned INMC(RHDPtr info, int addr)
{
u32_t data;
if ((info->ChipFamily == CHIP_FAMILY_RS690) ||
(info->ChipFamily == CHIP_FAMILY_RS740)) {
OUTREG(RS690_MC_INDEX, (addr & RS690_MC_INDEX_MASK));
data = INREG(RS690_MC_DATA);
} else if (info->ChipFamily == CHIP_FAMILY_RS600) {
OUTREG(RS600_MC_INDEX, (addr & RS600_MC_INDEX_MASK));
data = INREG(RS600_MC_DATA);
} else if (IS_AVIVO_VARIANT) {
OUTREG(AVIVO_MC_INDEX, (addr & 0xff) | 0x7f0000);
(void)INREG(AVIVO_MC_INDEX);
data = INREG(AVIVO_MC_DATA);
OUTREG(AVIVO_MC_INDEX, 0);
(void)INREG(AVIVO_MC_INDEX);
} else {
OUTREG(R300_MC_IND_INDEX, addr & 0x3f);
(void)INREG(R300_MC_IND_INDEX);
data = INREG(R300_MC_IND_DATA);
OUTREG(R300_MC_IND_INDEX, 0);
(void)INREG(R300_MC_IND_INDEX);
}
return data;
}
#define LOC_FB 0x1
#define LOC_AGP 0x2
static void radeon_read_mc_fb_agp_location(RHDPtr info, int mask,
u32_t *fb_loc, u32_t *agp_loc, u32_t *agp_loc_hi)
{
if (info->ChipFamily >= CHIP_FAMILY_RV770) {
if (mask & LOC_FB)
*fb_loc = INREG(R700_MC_VM_FB_LOCATION);
if (mask & LOC_AGP) {
*agp_loc = INREG(R600_MC_VM_AGP_BOT);
*agp_loc_hi = INREG(R600_MC_VM_AGP_TOP);
}
} else if (info->ChipFamily >= CHIP_FAMILY_R600) {
if (mask & LOC_FB)
*fb_loc = INREG(R600_MC_VM_FB_LOCATION);
if (mask & LOC_AGP) {
*agp_loc = INREG(R600_MC_VM_AGP_BOT);
*agp_loc_hi = INREG(R600_MC_VM_AGP_TOP);
}
} else if (info->ChipFamily == CHIP_FAMILY_RV515) {
if (mask & LOC_FB)
*fb_loc = INMC(info, RV515_MC_FB_LOCATION);
if (mask & LOC_AGP) {
*agp_loc = INMC(info, RV515_MC_AGP_LOCATION);
*agp_loc_hi = 0;
}
} else if (info->ChipFamily == CHIP_FAMILY_RS600) {
if (mask & LOC_FB)
*fb_loc = INMC(info, RS600_MC_FB_LOCATION);
if (mask & LOC_AGP) {
*agp_loc = 0;//INMC(pScrn, RS600_MC_AGP_LOCATION);
*agp_loc_hi = 0;
}
} else if ((info->ChipFamily == CHIP_FAMILY_RS690) ||
(info->ChipFamily == CHIP_FAMILY_RS740)) {
if (mask & LOC_FB)
*fb_loc = INMC(info, RS690_MC_FB_LOCATION);
if (mask & LOC_AGP) {
*agp_loc = INMC(info, RS690_MC_AGP_LOCATION);
*agp_loc_hi = 0;
}
} else if (info->ChipFamily >= CHIP_FAMILY_R520) {
if (mask & LOC_FB)
*fb_loc = INMC(info, R520_MC_FB_LOCATION);
if (mask & LOC_AGP) {
*agp_loc = INMC(info, R520_MC_AGP_LOCATION);
*agp_loc_hi = 0;
}
} else {
if (mask & LOC_FB)
*fb_loc = INREG(RADEON_MC_FB_LOCATION);
if (mask & LOC_AGP)
*agp_loc = INREG(RADEON_MC_AGP_LOCATION);
}
}
static void RADEONInitMemoryMap(RHDPtr info)
{
u32_t mem_size;
u32_t aper_size;
radeon_read_mc_fb_agp_location(info, LOC_FB | LOC_AGP, &info->mc_fb_location,
&info->mc_agp_location, &info->mc_agp_location_hi);
/* We shouldn't use info->videoRam here which might have been clipped
* but the real video RAM instead
*/
if (info->ChipFamily >= CHIP_FAMILY_R600){
mem_size = INREG(R600_CONFIG_MEMSIZE);
aper_size = INREG(R600_CONFIG_APER_SIZE);
}
else {
mem_size = INREG(RADEON_CONFIG_MEMSIZE);
aper_size = INREG(RADEON_CONFIG_APER_SIZE);
}
if (mem_size == 0)
mem_size = 0x800000;
/* Fix for RN50, M6, M7 with 8/16/32(??) MBs of VRAM -
Novell bug 204882 + along with lots of ubuntu ones */
if (aper_size > mem_size)
mem_size = aper_size;
if ( (info->ChipFamily != CHIP_FAMILY_RS600) &&
(info->ChipFamily != CHIP_FAMILY_RS690) &&
(info->ChipFamily != CHIP_FAMILY_RS740)) {
if (info->IsIGP)
info->mc_fb_location = INREG(RADEON_NB_TOM);
else
{
u32_t aper0_base;
if (info->ChipFamily >= CHIP_FAMILY_R600) {
aper0_base = INREG(R600_CONFIG_F0_BASE);
}
else {
aper0_base = INREG(RADEON_CONFIG_APER_0_BASE);
}
/* Recent chips have an "issue" with the memory controller, the
* location must be aligned to the size. We just align it down,
* too bad if we walk over the top of system memory, we don't
* use DMA without a remapped anyway.
* Affected chips are rv280, all r3xx, and all r4xx, but not IGP
*/
if ( info->ChipFamily == CHIP_FAMILY_RV280 ||
info->ChipFamily == CHIP_FAMILY_R300 ||
info->ChipFamily == CHIP_FAMILY_R350 ||
info->ChipFamily == CHIP_FAMILY_RV350 ||
info->ChipFamily == CHIP_FAMILY_RV380 ||
info->ChipFamily == CHIP_FAMILY_R420 ||
info->ChipFamily == CHIP_FAMILY_RV410)
aper0_base &= ~(mem_size - 1);
if ( info->ChipFamily >= CHIP_FAMILY_R600) {
info->mc_fb_location = (aper0_base >> 24) |
(((aper0_base + mem_size - 1) & 0xff000000U) >> 8);
dbgprintf("mc fb loc is %08x\n", (unsigned int)info->mc_fb_location);
}
else {
info->mc_fb_location = (aper0_base >> 16) |
((aper0_base + mem_size - 1) & 0xffff0000U);
}
}
}
if (info->ChipFamily >= CHIP_FAMILY_R600) {
info->fbLocation = (info->mc_fb_location & 0xffff) << 24;
}
else {
info->fbLocation = (info->mc_fb_location & 0xffff) << 16;
}
/* Just disable the damn AGP apertures for now, it may be
* re-enabled later by the DRM
*/
if (IS_AVIVO_VARIANT) {
if (info->ChipFamily >= CHIP_FAMILY_R600) {
OUTREG(R600_HDP_NONSURFACE_BASE, (info->mc_fb_location << 16) & 0xff0000);
}
else {
OUTREG(AVIVO_HDP_FB_LOCATION, info->mc_fb_location);
}
info->mc_agp_location = 0x003f0000;
}
else
info->mc_agp_location = 0xffffffc0;
dbgprintf("RADEONInitMemoryMap() : \n");
dbgprintf(" mem_size : 0x%08x\n", (unsigned)mem_size);
dbgprintf(" MC_FB_LOCATION : 0x%08x\n", (unsigned)info->mc_fb_location);
dbgprintf(" MC_AGP_LOCATION : 0x%08x\n", (unsigned)info->mc_agp_location);
}
static void RADEONGetVRamType(RHDPtr info)
{
u32_t tmp;
if (info->IsIGP || (info->ChipFamily >= CHIP_FAMILY_R300))
info->IsDDR = TRUE;
else if (INREG(RADEON_MEM_SDRAM_MODE_REG) & RADEON_MEM_CFG_TYPE_DDR)
info->IsDDR = TRUE;
else
info->IsDDR = FALSE;
if ( (info->ChipFamily >= CHIP_FAMILY_R600) &&
(info->ChipFamily <= CHIP_FAMILY_RV635))
{
int chansize;
/* r6xx */
tmp = INREG(R600_RAMCFG);
if (tmp & R600_CHANSIZE_OVERRIDE)
chansize = 16;
else if (tmp & R600_CHANSIZE)
chansize = 64;
else
chansize = 32;
if (info->ChipFamily == CHIP_FAMILY_R600)
info->RamWidth = 8 * chansize;
else if (info->ChipFamily == CHIP_FAMILY_RV670)
info->RamWidth = 4 * chansize;
else if ((info->ChipFamily == CHIP_FAMILY_RV610) ||
(info->ChipFamily == CHIP_FAMILY_RV620))
info->RamWidth = chansize;
else if ((info->ChipFamily == CHIP_FAMILY_RV630) ||
(info->ChipFamily == CHIP_FAMILY_RV635))
info->RamWidth = 2 * chansize;
}
else if (info->ChipFamily == CHIP_FAMILY_RV515) {
/* rv515/rv550 */
tmp = INMC(info, RV515_MC_CNTL);
tmp &= RV515_MEM_NUM_CHANNELS_MASK;
switch (tmp) {
case 0: info->RamWidth = 64; break;
case 1: info->RamWidth = 128; break;
default: info->RamWidth = 128; break;
}
}
else if ((info->ChipFamily >= CHIP_FAMILY_R520) &&
(info->ChipFamily <= CHIP_FAMILY_RV570)){
/* r520/rv530/rv560/rv570/r580 */
tmp = INMC(info, R520_MC_CNTL0);
switch ((tmp & R520_MEM_NUM_CHANNELS_MASK) >> R520_MEM_NUM_CHANNELS_SHIFT) {
case 0: info->RamWidth = 32; break;
case 1: info->RamWidth = 64; break;
case 2: info->RamWidth = 128; break;
case 3: info->RamWidth = 256; break;
default: info->RamWidth = 64; break;
}
if (tmp & R520_MC_CHANNEL_SIZE) {
info->RamWidth *= 2;
}
}
else if ((info->ChipFamily >= CHIP_FAMILY_R300) &&
(info->ChipFamily <= CHIP_FAMILY_RV410)) {
/* r3xx, r4xx */
tmp = INREG(RADEON_MEM_CNTL);
tmp &= R300_MEM_NUM_CHANNELS_MASK;
switch (tmp) {
case 0: info->RamWidth = 64; break;
case 1: info->RamWidth = 128; break;
case 2: info->RamWidth = 256; break;
default: info->RamWidth = 128; break;
}
}
else if ((info->ChipFamily == CHIP_FAMILY_RV100) ||
(info->ChipFamily == CHIP_FAMILY_RS100) ||
(info->ChipFamily == CHIP_FAMILY_RS200)){
tmp = INREG(RADEON_MEM_CNTL);
if (tmp & RV100_HALF_MODE)
info->RamWidth = 32;
else
info->RamWidth = 64;
/// if (!info->HasCRTC2) {
/// info->RamWidth /= 4;
/// info->IsDDR = TRUE;
/// }
}
else if (info->ChipFamily <= CHIP_FAMILY_RV280) {
tmp = INREG(RADEON_MEM_CNTL);
if (tmp & RADEON_MEM_NUM_CHANNELS_MASK)
info->RamWidth = 128;
else
info->RamWidth = 64;
} else {
/* newer IGPs */
info->RamWidth = 128;
}
/* This may not be correct, as some cards can have half of channel disabled
* ToDo: identify these cases
*/
}
/*
* Depending on card genertation, chipset bugs, etc... the amount of vram
* accessible to the CPU can vary. This function is our best shot at figuring
* it out. Returns a value in KB.
*/
static u32_t RADEONGetAccessibleVRAM(RHDPtr info)
{
u32_t aper_size;
unsigned char byte;
if (info->ChipFamily >= CHIP_FAMILY_R600)
aper_size = INREG(R600_CONFIG_APER_SIZE) / 1024;
else
aper_size = INREG(RADEON_CONFIG_APER_SIZE) / 1024;
/* Set HDP_APER_CNTL only on cards that are known not to be broken,
* that is has the 2nd generation multifunction PCI interface
*/
if (info->ChipFamily == CHIP_FAMILY_RV280 ||
info->ChipFamily == CHIP_FAMILY_RV350 ||
info->ChipFamily == CHIP_FAMILY_RV380 ||
info->ChipFamily == CHIP_FAMILY_R420 ||
info->ChipFamily == CHIP_FAMILY_RV410 ||
IS_AVIVO_VARIANT) {
MASKREG (RADEON_HOST_PATH_CNTL, RADEON_HDP_APER_CNTL,
~RADEON_HDP_APER_CNTL);
dbgprintf("Generation 2 PCI interface, using max accessible memory\n");
return aper_size * 2;
}
/* Older cards have all sorts of funny issues to deal with. First
* check if it's a multifunction card by reading the PCI config
* header type... Limit those to one aperture size
*/
// PCI_READ_BYTE(info->PciInfo, &byte, 0xe);
// if (byte & 0x80) {
// xf86DrvMsg(pScrn->scrnIndex, X_INFO,
// "Generation 1 PCI interface in multifunction mode"
// ", accessible memory limited to one aperture\n");
// return aper_size;
// }
/* Single function older card. We read HDP_APER_CNTL to see how the BIOS
* have set it up. We don't write this as it's broken on some ASICs but
* we expect the BIOS to have done the right thing (might be too optimistic...)
*/
// if (INREG(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL)
// return aper_size * 2;
return aper_size;
}
static Bool RADEONPreInitVRAM(RHDPtr info)
{
u32_t accessible, bar_size;
if ((!IS_AVIVO_VARIANT) && info->IsIGP)
{
u32_t tom = INREG(RADEON_NB_TOM);
info->videoRam = (((tom >> 16) -
(tom & 0xffff) + 1) << 6);
OUTREG(RADEON_CONFIG_MEMSIZE, info->videoRam * 1024);
}
else
{
if (info->ChipFamily >= CHIP_FAMILY_R600)
info->videoRam = INREG(R600_CONFIG_MEMSIZE) / 1024;
else
{
/* Read VRAM size from card */
info->videoRam = INREG(RADEON_CONFIG_MEMSIZE) / 1024;
/* Some production boards of m6 will return 0 if it's 8 MB */
if (info->videoRam == 0)
{
info->videoRam = 8192;
OUTREG(RADEON_CONFIG_MEMSIZE, 0x800000);
}
}
}
RADEONGetVRamType(info);
/* Get accessible memory */
accessible = RADEONGetAccessibleVRAM(info);
/* Crop it to the size of the PCI BAR */
// bar_size = PCI_REGION_SIZE(info->PciInfo, 0) / 1024;
bar_size = 1 << (info->memsize[RHD_FB_BAR] - 10);
if (bar_size == 0)
bar_size = 0x20000;
if (accessible > bar_size)
accessible = bar_size;
dbgprintf("Detected total video RAM=%dK width=%dbit,"
"accessible=%uK (PCI BAR=%uK)\n",
info->videoRam, info->RamWidth,
(unsigned)accessible, (unsigned)bar_size);
if (info->videoRam > accessible)
info->videoRam = accessible;
if (!IS_AVIVO_VARIANT)
info->MemCntl = INREG(RADEON_SDRAM_MODE_REG);
info->BusCntl = INREG(RADEON_BUS_CNTL);
info->videoRam &= ~1023;
info->FbMapSize = info->videoRam * 1024;
/* if the card is PCI Express reserve the last 32k for the gart table */
// if (info->cardType == CARD_PCIE )
/* work out the size of pcie aperture */
// info->FbSecureSize = RADEONDRIGetPciAperTableSize(info);
// else
// info->FbSecureSize = 0;
return TRUE;
}
/*
#define RADEON_NB_TOM 0x15c
static size_t rhdGetVideoRamSize(RHDPtr rhdPtr)
{
size_t RamSize, BARSize;
if (rhdPtr->ChipFamily == CHIP_FAMILY_RS690)
RamSize = (_RHDRegRead(rhdPtr, R5XX_CONFIG_MEMSIZE))>>10;
else
if (rhdPtr->IsIGP)
{
u32_t tom = _RHDRegRead(rhdPtr, RADEON_NB_TOM);
RamSize = (((tom >> 16) - (tom & 0xffff) + 1) << 6);
_RHDRegWrite(rhdPtr,R5XX_CONFIG_MEMSIZE, RamSize<<10);
}
else
{
if (rhdPtr->ChipFamily < CHIP_FAMILY_R600)
{
RamSize = (_RHDRegRead(rhdPtr, R5XX_CONFIG_MEMSIZE)) >> 10;
if(RamSize==0) RamSize=8192;
}
else
RamSize = (_RHDRegRead(rhdPtr, R6XX_CONFIG_MEMSIZE)) >> 10;
};
BARSize = 1 << (rhdPtr->memsize[RHD_FB_BAR] - 10);
if(BARSize==0)
BARSize = 0x20000;
if (RamSize > BARSize) {
DBG(dbgprintf("The detected amount of videoram"
" exceeds the PCI BAR aperture.\n"));
DBG(dbgprintf("Using only %dkB of the total "
"%dkB.\n", (int) BARSize, (int) RamSize));
return BARSize;
}
else return RamSize;
}
*/
#if 0
static Bool
rhdMapFB(RHDPtr rhdPtr)
{
rhdPtr->FbMapSize = 1 << rhdPtr->memsize[RHD_FB_BAR];
rhdPtr->PhisBase = rhdPtr->memBase[RHD_FB_BAR];
// rhdPtr->FbBase = MapIoMem(rhdPtr->PhisBase, rhdPtr->FbMapSize,PG_SW+PG_NOCACHE);
// if (!rhdPtr->FbBase)
// return FALSE;
/* These devices have an internal address reference, which some other
* address registers in there also use. This can be different from the
* address in the BAR */
if (rhdPtr->ChipFamily < CHIP_FAMILY_R600)
rhdPtr->FbIntAddress = _RHDRegRead(rhdPtr, HDP_FB_LOCATION)<< 16;
else
rhdPtr->FbIntAddress = _RHDRegRead(rhdPtr, R6XX_CONFIG_FB_BASE);
// rhdPtr->FbIntAddress = _RHDRegRead(rhdPtr, 0x6110);
// dbgprintf("rhdPtr->FbIntAddress %x\n",rhdPtr->FbIntAddress);
if (rhdPtr->FbIntAddress != rhdPtr->PhisBase)
dbgprintf("PCI FB Address (BAR) is at "
"0x%08X while card Internal Address is 0x%08X\n",
(unsigned int) rhdPtr->PhisBase,rhdPtr->FbIntAddress);
// dbgprintf("Mapped FB at %p (size 0x%08X)\n",rhdPtr->FbBase, rhdPtr->FbMapSize);
return TRUE;
}
#endif
static Bool RADEONPreInitChipType(RHDPtr rhdPtr)
{
u32_t cmd_stat;
rhdPtr->ChipErrata = 0;
if ( (rhdPtr->ChipFamily == CHIP_FAMILY_R300) &&
((_RHDRegRead(rhdPtr,RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK)
== RADEON_CFG_ATI_REV_A11))
rhdPtr->ChipErrata |= CHIP_ERRATA_R300_CG;
if ( (rhdPtr->ChipFamily == CHIP_FAMILY_RV200) ||
(rhdPtr->ChipFamily == CHIP_FAMILY_RS200) )
rhdPtr->ChipErrata |= CHIP_ERRATA_PLL_DUMMYREADS;
if ( (rhdPtr->ChipFamily == CHIP_FAMILY_RV100) ||
(rhdPtr->ChipFamily == CHIP_FAMILY_RS100) ||
(rhdPtr->ChipFamily == CHIP_FAMILY_RS200) )
rhdPtr->ChipErrata |= CHIP_ERRATA_PLL_DELAY;
rhdPtr->cardType = CARD_PCI;
cmd_stat = pciReadLong(rhdPtr->PciTag, PCI_CMD_STAT_REG);
if (cmd_stat & RADEON_CAP_LIST)
{
u32_t cap_ptr, cap_id;
cap_ptr = pciReadLong(rhdPtr->PciTag, RADEON_CAPABILITIES_PTR_PCI_CONFIG);
cap_ptr &= RADEON_CAP_PTR_MASK;
while(cap_ptr != RADEON_CAP_ID_NULL)
{
cap_id = pciReadLong(rhdPtr->PciTag, cap_ptr);
if ((cap_id & 0xff)== RADEON_CAP_ID_AGP) {
rhdPtr->cardType = CARD_AGP;
break;
}
if ((cap_id & 0xff)== RADEON_CAP_ID_EXP) {
rhdPtr->cardType = CARD_PCIE;
break;
}
cap_ptr = (cap_id >> 8) & RADEON_CAP_PTR_MASK;
}
}
dbgprintf("%s card detected\n",(rhdPtr->cardType==CARD_PCI) ? "PCI" :
(rhdPtr->cardType==CARD_PCIE) ? "PCIE" : "AGP");
/* treat PCIE IGP cards as PCI */
if (rhdPtr->cardType == CARD_PCIE && rhdPtr->IsIGP)
rhdPtr->cardType = CARD_PCI;
if ( (rhdPtr->ChipFamily == CHIP_FAMILY_RS100) ||
(rhdPtr->ChipFamily == CHIP_FAMILY_RS200) ||
(rhdPtr->ChipFamily == CHIP_FAMILY_RS300) ||
(rhdPtr->ChipFamily == CHIP_FAMILY_RS400) ||
(rhdPtr->ChipFamily == CHIP_FAMILY_RS480) ||
(rhdPtr->ChipFamily == CHIP_FAMILY_RS600) ||
(rhdPtr->ChipFamily == CHIP_FAMILY_RS690) ||
(rhdPtr->ChipFamily == CHIP_FAMILY_RS740))
rhdPtr->has_tcl = FALSE;
else {
rhdPtr->has_tcl = TRUE;
}
rhdPtr->LinearAddr = rhdPtr->memBase[RHD_FB_BAR];
return TRUE;
}
Bool RHDPreInit()
{
/* We need access to IO space already */
if ( !rhdMapMMIO(&rhd) ) {
dbgprintf("Failed to map MMIO.\n");
return FALSE;
};
if( !RADEONPreInitChipType(&rhd))
return FALSE;
if (!RADEONPreInitVRAM(&rhd))
return FALSE;
RADEONInitMemoryMap(&rhd);
if (!rhd.videoRam)
{
dbgprintf("No Video RAM detected.\n");
goto error1;
}
dbgprintf("VideoRAM: %d kByte\n",rhd.videoRam);
rhd.FbFreeStart = 0;
rhd.FbFreeSize = rhd.videoRam << 10;
// if( !rhdMapFB(&rhd))
// return FALSE;
// rhd.FbScanoutStart = 0;
// rhd.FbScanoutSize = 8*1024*1024;
rhd.FbFreeStart = 10*1024*1024;
rhd.FbFreeSize = rhd.FbMapSize - rhd.FbFreeStart;
rhdInitHeap(&rhd);
return TRUE;
error1:
return FALSE;
};