#include "ati.h"
#include "atichip.h"
#include "aticrtc.h"
#include "atidsp.h"
#include "atimach64io.h"
#include "atividmem.h"
Bool
ATIDSPPreInit
(
int iScreen,
ATIPtr pATI
)
{
CARD32 IOValue, dsp_config, dsp_on_off, vga_dsp_config, vga_dsp_on_off;
int trp;
pATI->ClockDescriptor.NumD = 8;
IOValue = ATIMach64GetPLLReg(PLL_XCLK_CNTL);
pATI->XCLKPostDivider = GetBits(IOValue, PLL_XCLK_SRC_SEL);
pATI->XCLKReferenceDivider = 1;
switch (pATI->XCLKPostDivider)
{
case 0: case 1: case 2: case 3:
break;
case 4:
pATI->XCLKReferenceDivider = 3;
pATI->XCLKPostDivider = 0;
break;
default:
xf86DrvMsg(iScreen, X_ERROR,
"Unsupported XCLK source: %d.\n", pATI->XCLKPostDivider);
return FALSE;
}
pATI->XCLKPostDivider -= GetBits(IOValue, PLL_MFB_TIMES_4_2B);
pATI->XCLKFeedbackDivider = ATIMach64GetPLLReg(PLL_MCLK_FB_DIV);
xf86DrvMsgVerb(iScreen, X_INFO, 2,
"Engine XCLK %.3f MHz; Refresh rate code %ld.\n",
ATIDivide(pATI->XCLKFeedbackDivider * pATI->ReferenceNumerator,
pATI->XCLKReferenceDivider * pATI->ClockDescriptor.MaxM *
pATI->ReferenceDenominator, 1 - pATI->XCLKPostDivider, 0) /
(double)1000.0,
GetBits(pATI->LockData.mem_cntl, CTL_MEM_REFRESH_RATE_B));
trp = GetBits(pATI->LockData.mem_cntl, CTL_MEM_TRP);
pATI->XCLKPageFaultDelay = GetBits(pATI->LockData.mem_cntl, CTL_MEM_TRCD) +
GetBits(pATI->LockData.mem_cntl, CTL_MEM_TCRD) + trp + 2;
pATI->XCLKMaxRASDelay = GetBits(pATI->LockData.mem_cntl, CTL_MEM_TRAS) +
trp + 2;
pATI->DisplayFIFODepth = 32;
if (pATI->Chip < ATI_CHIP_264VT4)
{
pATI->XCLKPageFaultDelay += 2;
pATI->XCLKMaxRASDelay += 3;
pATI->DisplayFIFODepth = 24;
}
switch (pATI->MemoryType)
{
case MEM_264_DRAM:
if (pATI->VideoRAM <= 1024)
{
pATI->DisplayLoopLatency = 10;
}
else
{
pATI->DisplayLoopLatency = 8;
pATI->XCLKPageFaultDelay += 2;
}
break;
case MEM_264_EDO:
case MEM_264_PSEUDO_EDO:
if (pATI->VideoRAM <= 1024)
{
pATI->DisplayLoopLatency = 9;
}
else
{
pATI->DisplayLoopLatency = 8;
pATI->XCLKPageFaultDelay++;
}
break;
case MEM_264_SDRAM:
if (pATI->VideoRAM <= 1024)
{
pATI->DisplayLoopLatency = 11;
}
else
{
pATI->DisplayLoopLatency = 10;
pATI->XCLKPageFaultDelay++;
}
break;
case MEM_264_SGRAM:
pATI->DisplayLoopLatency = 8;
pATI->XCLKPageFaultDelay += 3;
break;
default:
pATI->DisplayLoopLatency = 11;
pATI->XCLKPageFaultDelay += 3;
break;
}
if (pATI->XCLKMaxRASDelay <= pATI->XCLKPageFaultDelay)
pATI->XCLKMaxRASDelay = pATI->XCLKPageFaultDelay + 1;
dsp_config = inr(DSP_CONFIG);
dsp_on_off = inr(DSP_ON_OFF);
vga_dsp_config = inr(VGA_DSP_CONFIG);
vga_dsp_on_off = inr(VGA_DSP_ON_OFF);
if (dsp_config)
pATI->DisplayLoopLatency = GetBits(dsp_config, DSP_LOOP_LATENCY);
if ((!dsp_on_off && (pATI->Chip < ATI_CHIP_264GTPRO)) ||
((dsp_on_off == vga_dsp_on_off) &&
(!dsp_config || !((dsp_config ^ vga_dsp_config) & DSP_XCLKS_PER_QW))))
{
if (ATIDivide(GetBits(vga_dsp_on_off, VGA_DSP_OFF),
GetBits(vga_dsp_config, VGA_DSP_XCLKS_PER_QW), 5, 1) > 24)
pATI->DisplayFIFODepth = 32;
else
pATI->DisplayFIFODepth = 24;
}
return TRUE;
}
void
ATIDSPSave
(
ATIPtr pATI,
ATIHWPtr pATIHW
)
{
pATIHW->dsp_on_off = inr(DSP_ON_OFF);
pATIHW->dsp_config = inr(DSP_CONFIG);
}
void
ATIDSPCalculate
(
ATIPtr pATI,
ATIHWPtr pATIHW,
DisplayModePtr pMode
)
{
int Multiplier, Divider;
int RASMultiplier = pATI->XCLKMaxRASDelay, RASDivider = 1;
int dsp_precision, dsp_on, dsp_off, dsp_xclks;
int tmp, vshift, xshift;
# define Maximum_DSP_PRECISION ((int)MaxBits(DSP_PRECISION))
Multiplier = pATI->XCLKFeedbackDivider *
pATI->ClockDescriptor.PostDividers[pATIHW->PostDivider];
Divider = pATIHW->FeedbackDivider * pATI->XCLKReferenceDivider;
#ifndef AVOID_CPIO
if (pATI->depth >= 8)
#endif
{
Divider *= pATI->bitsPerPixel / 4;
}
vshift = (6 - 2) - pATI->XCLKPostDivider;
#ifndef AVOID_CPIO
if (pATIHW->crtc == ATI_CRTC_VGA)
vshift--;
#endif
if (pATI->OptionPanelDisplay && (pATI->LCDPanelID >= 0))
{
Multiplier *= pATI->LCDHorizontal;
Divider *= pMode->HDisplay & ~7;
RASMultiplier *= pATI->LCDHorizontal;
RASDivider *= pMode->HDisplay & ~7;
}
tmp = ATIDivide(Multiplier * pATI->DisplayFIFODepth, Divider, vshift, -1);
for (dsp_precision = -5; tmp; dsp_precision++)
tmp >>= 1;
if (dsp_precision < 0)
dsp_precision = 0;
else if (dsp_precision > Maximum_DSP_PRECISION)
dsp_precision = Maximum_DSP_PRECISION;
xshift = 6 - dsp_precision;
vshift += xshift;
dsp_off = ATIDivide(Multiplier * (pATI->DisplayFIFODepth - 1), Divider,
vshift, -1) - ATIDivide(1, 1, vshift - xshift, 1);
#ifndef AVOID_CPIO
if ((pATIHW->crtc == ATI_CRTC_VGA) )
{
dsp_on = ATIDivide(Multiplier * 5, Divider, vshift + 2, 1);
}
else
#endif
{
dsp_on = ATIDivide(Multiplier, Divider, vshift, 1);
tmp = ATIDivide(RASMultiplier, RASDivider, xshift, 1);
if (dsp_on < tmp)
dsp_on = tmp;
dsp_on += (tmp * 2) +
ATIDivide(pATI->XCLKPageFaultDelay, 1, xshift, 1);
}
tmp = ((1 << (Maximum_DSP_PRECISION - dsp_precision)) - 1) >> 1;
dsp_on = ((dsp_on + tmp) / (tmp + 1)) * (tmp + 1);
if (dsp_on >= ((dsp_off / (tmp + 1)) * (tmp + 1)))
{
dsp_on = dsp_off - ATIDivide(Multiplier, Divider, vshift, -1);
dsp_on = (dsp_on / (tmp + 1)) * (tmp + 1);
}
dsp_xclks = ATIDivide(Multiplier, Divider, vshift + 5, 1);
pATIHW->dsp_on_off = SetBits(dsp_on, DSP_ON) |
SetBits(dsp_off, DSP_OFF);
pATIHW->dsp_config = SetBits(dsp_precision, DSP_PRECISION) |
SetBits(dsp_xclks, DSP_XCLKS_PER_QW) |
SetBits(pATI->DisplayLoopLatency, DSP_LOOP_LATENCY);
}
void
ATIDSPSet
(
ATIPtr pATI,
ATIHWPtr pATIHW
)
{
outr(DSP_ON_OFF, pATIHW->dsp_on_off);
outr(DSP_CONFIG, pATIHW->dsp_config);
}