#include "atiadapter.h"
#include "atichip.h"
#include "aticrtc.h"
#include "atistruct.h"
#include "ativalid.h"
#include "xf86.h"
ModeStatus
ATIValidMode
(
int iScreen,
DisplayModePtr pMode,
Bool Verbose,
int flags
)
{
ScrnInfoPtr pScreenInfo = xf86Screens[iScreen];
ATIPtr pATI = ATIPTR(pScreenInfo);
Bool InterlacedSeen;
int HBlankWidth, HAdjust, VScan, VInterlace;
#ifndef AVOID_CPIO
int VDisplay, VTotal;
#endif
if (flags & MODECHECK_FINAL)
{
if (pATI->MaximumInterlacedPitch)
{
if (pMode->Flags & V_INTERLACE)
InterlacedSeen = TRUE;
else
InterlacedSeen = pATI->InterlacedSeen;
if (InterlacedSeen &&
(pScreenInfo->displayWidth > pATI->MaximumInterlacedPitch))
return MODE_INTERLACE_WIDTH;
pATI->InterlacedSeen = InterlacedSeen;
}
return MODE_OK;
}
if (pMode->VScan <= 1)
VScan = 1;
else
VScan = pMode->VScan;
if (pMode->Flags & V_DBLSCAN)
VScan <<= 1;
if (pATI->OptionPanelDisplay && (pATI->LCDPanelID >= 0))
{
if ((pMode->CrtcHDisplay > pATI->LCDHorizontal) ||
(pMode->CrtcVDisplay > pATI->LCDVertical))
return MODE_PANEL;
if (!pATI->OptionLCDSync || (pMode->type & M_T_BUILTIN))
{
if ((pMode->HDisplay > pATI->LCDHorizontal) ||
(pMode->VDisplay > pATI->LCDVertical))
return MODE_PANEL;
return MODE_OK;
}
pMode->SynthClock = pATI->LCDClock;
pMode->CrtcHTotal = pMode->CrtcHBlankEnd =
ATIDivide(pMode->CrtcHTotal * pATI->LCDHorizontal,
pMode->CrtcHDisplay, -3, 1) << 3;
pMode->CrtcHSyncEnd =
ATIDivide(pMode->CrtcHSyncEnd * pATI->LCDHorizontal,
pMode->CrtcHDisplay, -3, 1) << 3;
pMode->CrtcHSyncStart =
ATIDivide(pMode->CrtcHSyncStart * pATI->LCDHorizontal,
pMode->CrtcHDisplay, -3, -1) << 3;
pMode->CrtcHDisplay = pMode->CrtcHBlankStart = pATI->LCDHorizontal;
pMode->CrtcVTotal = pMode->CrtcVBlankEnd =
ATIDivide((pMode->CrtcVTotal - pMode->CrtcVDisplay) *
pATI->LCDVertical, pATI->LCDHorizontal, 0, 1) +
pATI->LCDVertical;
pMode->CrtcVSyncEnd =
ATIDivide((pMode->CrtcVSyncEnd - pMode->CrtcVDisplay) *
pATI->LCDVertical, pATI->LCDHorizontal, 0, 1) +
pATI->LCDVertical;
pMode->CrtcVSyncStart =
ATIDivide((pMode->CrtcVSyncStart - pMode->CrtcVDisplay) *
pATI->LCDVertical, pATI->LCDHorizontal, 0, -1) +
pATI->LCDVertical;
pMode->CrtcVDisplay = pMode->CrtcVBlankStart = pATI->LCDVertical;
pMode->Clock = pATI->LCDClock;
HAdjust = pATI->LCDHorizontal - pMode->HDisplay;
# define ATIReverseHorizontal(_x) \
(pMode->_x - HAdjust)
pMode->HSyncStart = ATIReverseHorizontal(CrtcHSyncStart);
pMode->HSyncEnd = ATIReverseHorizontal(CrtcHSyncEnd);
pMode->HTotal = ATIReverseHorizontal(CrtcHTotal);
VInterlace = GetBits(pMode->Flags, V_INTERLACE) + 1;
# define ATIReverseVertical(_y) \
((((pMode->_y - pATI->LCDVertical) * VInterlace) / VScan) + \
pMode->VDisplay)
pMode->VSyncStart = ATIReverseVertical(CrtcVSyncStart);
pMode->VSyncEnd = ATIReverseVertical(CrtcVSyncEnd);
pMode->VTotal = ATIReverseVertical(CrtcVTotal);
# undef ATIReverseHorizontal
# undef ATIReverseVertical
}
HBlankWidth = (pMode->HTotal >> 3) - (pMode->HDisplay >> 3);
if (!HBlankWidth)
return MODE_HBLANK_NARROW;
switch (pATI->NewHW.crtc)
{
#ifndef AVOID_CPIO
case ATI_CRTC_VGA:
if (HBlankWidth > 63)
return MODE_HBLANK_WIDE;
if (pMode->HDisplay > 2048)
return MODE_BAD_HVALUE;
if (VScan > 64)
return MODE_BAD_VSCAN;
VDisplay = pMode->VDisplay * VScan;
VTotal = pMode->VTotal * VScan;
if ((pMode->Flags & V_INTERLACE) && (pATI->Chip < ATI_CHIP_264CT))
{
VDisplay >>= 1;
VTotal >>= 1;
}
if ((VDisplay > 2048) || (VTotal > 2050))
return MODE_BAD_VVALUE;
if (pATI->Adapter != ATI_ADAPTER_VGA)
break;
if ((VDisplay > 1024) || (VTotal > 1025))
return MODE_BAD_VVALUE;
break;
#endif
case ATI_CRTC_MACH64:
if (VScan > 2)
return MODE_NO_VSCAN;
break;
default:
break;
}
return MODE_OK;
}