1
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/ativalid.c,v 1.15 2003/01/01 19:16:34 tsi Exp $ */
3
* Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
5
* Permission to use, copy, modify, distribute, and sell this software and its
6
* documentation for any purpose is hereby granted without fee, provided that
7
* the above copyright notice appear in all copies and that both that copyright
8
* notice and this permission notice appear in supporting documentation, and
9
* that the name of Marc Aurele La France not be used in advertising or
10
* publicity pertaining to distribution of the software without specific,
11
* written prior permission. Marc Aurele La France makes no representations
12
* about the suitability of this software for any purpose. It is provided
13
* "as-is" without express or implied warranty.
15
* MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
17
* EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21
* PERFORMANCE OF THIS SOFTWARE.
24
#include "atiadapter.h"
27
#include "atistruct.h"
35
* This checks for hardware-related limits on mode timings.
46
ScrnInfoPtr pScreenInfo = xf86Screens[iScreen];
47
ATIPtr pATI = ATIPTR(pScreenInfo);
49
int HBlankWidth, HAdjust, VScan, VInterlace;
55
#endif /* AVOID_CPIO */
57
if (flags & MODECHECK_FINAL)
60
* This is the final check before the common layer accepts a mode.
61
* pScreenInfo->displayWidth is set to the proposed virtual pitch
62
* should the mode be accepted. The only check needed here is for
63
* 18800's and 28800's, which don't support interlaced modes if the
64
* pitch is over half the chipset's maximum pitch.
66
if (pATI->MaximumInterlacedPitch)
69
* Ensure no interlaced modes have a scanline pitch larger than the
72
if (pMode->Flags & V_INTERLACE)
73
InterlacedSeen = TRUE;
75
InterlacedSeen = pATI->InterlacedSeen;
78
(pScreenInfo->displayWidth > pATI->MaximumInterlacedPitch))
79
return MODE_INTERLACE_WIDTH;
81
pATI->InterlacedSeen = InterlacedSeen;
88
* The following is done for every mode in the monitor section that
89
* survives the common layer's basic checks.
91
if (pMode->VScan <= 1)
96
if (pMode->Flags & V_DBLSCAN)
99
if (pATI->OptionPanelDisplay && (pATI->LCDPanelID >= 0))
101
if ((pMode->CrtcHDisplay > pATI->LCDHorizontal) ||
102
(pMode->CrtcVDisplay > pATI->LCDVertical))
105
if (!pATI->OptionSync || (pMode->type & M_T_BUILTIN))
107
if ((pMode->HDisplay > pATI->LCDHorizontal) ||
108
(pMode->VDisplay > pATI->LCDVertical))
115
* Adjust effective timings for monitor checks. Here the modeline
116
* clock is ignored. Horizontal timings are scaled by the stretch
117
* ratio used for the displayed area. The vertical porch is scaled by
118
* the native resolution's aspect ratio. This seems rather arbitrary,
119
* and it is, but it does make all applicable VESA modes sync on a
120
* panel after stretching. This has the unfortunate, but necessary,
121
* side-effect of changing the mode's horizontal sync and vertical
122
* refresh rates. With some exceptions, this tends to increase the
123
* mode's horizontal sync rate, and decrease its vertical refresh rate.
125
pMode->SynthClock = pATI->LCDClock;
127
pMode->CrtcHTotal = pMode->CrtcHBlankEnd =
128
ATIDivide(pMode->CrtcHTotal * pATI->LCDHorizontal,
129
pMode->CrtcHDisplay, -3, 1) << 3;
130
pMode->CrtcHSyncEnd =
131
ATIDivide(pMode->CrtcHSyncEnd * pATI->LCDHorizontal,
132
pMode->CrtcHDisplay, -3, 1) << 3;
133
pMode->CrtcHSyncStart =
134
ATIDivide(pMode->CrtcHSyncStart * pATI->LCDHorizontal,
135
pMode->CrtcHDisplay, -3, -1) << 3;
136
pMode->CrtcHDisplay = pMode->CrtcHBlankStart = pATI->LCDHorizontal;
138
pMode->CrtcVTotal = pMode->CrtcVBlankEnd =
139
ATIDivide((pMode->CrtcVTotal - pMode->CrtcVDisplay) *
140
pATI->LCDVertical, pATI->LCDHorizontal, 0, 1) +
142
pMode->CrtcVSyncEnd =
143
ATIDivide((pMode->CrtcVSyncEnd - pMode->CrtcVDisplay) *
144
pATI->LCDVertical, pATI->LCDHorizontal, 0, 1) +
146
pMode->CrtcVSyncStart =
147
ATIDivide((pMode->CrtcVSyncStart - pMode->CrtcVDisplay) *
148
pATI->LCDVertical, pATI->LCDHorizontal, 0, -1) +
150
pMode->CrtcVDisplay = pMode->CrtcVBlankStart = pATI->LCDVertical;
153
* The CRTC only stretches the mode's displayed area, not its porches.
154
* Reverse-engineer the mode's timings back into the user specified
155
* values so that the stretched mode is produced when the CRTC is
156
* eventually programmed. The reverse-engineered mode is then checked
157
* against CRTC limits below.
159
pMode->Clock = pATI->LCDClock;
161
HAdjust = pATI->LCDHorizontal - pMode->HDisplay;
162
# define ATIReverseHorizontal(_x) \
163
(pMode->_x - HAdjust)
165
pMode->HSyncStart = ATIReverseHorizontal(CrtcHSyncStart);
166
pMode->HSyncEnd = ATIReverseHorizontal(CrtcHSyncEnd);
167
pMode->HTotal = ATIReverseHorizontal(CrtcHTotal);
169
VInterlace = GetBits(pMode->Flags, V_INTERLACE) + 1;
170
# define ATIReverseVertical(_y) \
171
((((pMode->_y - pATI->LCDVertical) * VInterlace) / VScan) + \
174
pMode->VSyncStart = ATIReverseVertical(CrtcVSyncStart);
175
pMode->VSyncEnd = ATIReverseVertical(CrtcVSyncEnd);
176
pMode->VTotal = ATIReverseVertical(CrtcVTotal);
178
# undef ATIReverseHorizontal
179
# undef ATIReverseVertical
182
HBlankWidth = (pMode->HTotal >> 3) - (pMode->HDisplay >> 3);
184
return MODE_HBLANK_NARROW;
186
switch (pATI->NewHW.crtc)
192
/* Prevent overscans */
193
if (HBlankWidth > 63)
194
return MODE_HBLANK_WIDE;
196
if (pMode->HDisplay > 2048)
197
return MODE_BAD_HVALUE;
200
return MODE_BAD_VSCAN;
202
VDisplay = pMode->VDisplay * VScan;
203
VTotal = pMode->VTotal * VScan;
205
if ((pMode->Flags & V_INTERLACE) && (pATI->Chip < ATI_CHIP_264CT))
211
if ((VDisplay > 2048) || (VTotal > 2050))
212
return MODE_BAD_VVALUE;
214
if (pATI->Adapter != ATI_ADAPTER_VGA)
217
if ((VDisplay > 1024) || (VTotal > 1025))
218
return MODE_BAD_VVALUE;
222
#endif /* AVOID_CPIO */
224
case ATI_CRTC_MACH64:
226
return MODE_NO_VSCAN;