1*4882a593Smuzhiyun #define DEBUG_VERB 2
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright © 2002 David Dawes
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Permission is hereby granted, free of charge, to any person obtaining a
6*4882a593Smuzhiyun * copy of this software and associated documentation files (the "Software"),
7*4882a593Smuzhiyun * to deal in the Software without restriction, including without limitation
8*4882a593Smuzhiyun * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9*4882a593Smuzhiyun * and/or sell copies of the Software, and to permit persons to whom the
10*4882a593Smuzhiyun * Software is furnished to do so, subject to the following conditions:
11*4882a593Smuzhiyun *
12*4882a593Smuzhiyun * The above copyright notice and this permission notice shall be included in
13*4882a593Smuzhiyun * all copies or substantial portions of the Software.
14*4882a593Smuzhiyun *
15*4882a593Smuzhiyun * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*4882a593Smuzhiyun * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*4882a593Smuzhiyun * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18*4882a593Smuzhiyun * THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19*4882a593Smuzhiyun * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
20*4882a593Smuzhiyun * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21*4882a593Smuzhiyun * SOFTWARE.
22*4882a593Smuzhiyun *
23*4882a593Smuzhiyun * Except as contained in this notice, the name of the author(s) shall
24*4882a593Smuzhiyun * not be used in advertising or otherwise to promote the sale, use or other
25*4882a593Smuzhiyun * dealings in this Software without prior written authorization from
26*4882a593Smuzhiyun * the author(s).
27*4882a593Smuzhiyun *
28*4882a593Smuzhiyun * Authors: David Dawes <dawes@xfree86.org>
29*4882a593Smuzhiyun *
30*4882a593Smuzhiyun */
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun #ifdef HAVE_XORG_CONFIG_H
33*4882a593Smuzhiyun #include <xorg-config.h>
34*4882a593Smuzhiyun #endif
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun #include <stdio.h>
37*4882a593Smuzhiyun #include <string.h>
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun #include "xf86.h"
40*4882a593Smuzhiyun #include "vbe.h"
41*4882a593Smuzhiyun #include "vbeModes.h"
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun static int
GetDepthFlag(vbeInfoPtr pVbe,int id)44*4882a593Smuzhiyun GetDepthFlag(vbeInfoPtr pVbe, int id)
45*4882a593Smuzhiyun {
46*4882a593Smuzhiyun VbeModeInfoBlock *mode;
47*4882a593Smuzhiyun int bpp;
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun if ((mode = VBEGetModeInfo(pVbe, id)) == NULL)
50*4882a593Smuzhiyun return 0;
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun if (VBE_MODE_USABLE(mode, 0)) {
53*4882a593Smuzhiyun int depth;
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun if (VBE_MODE_COLOR(mode)) {
56*4882a593Smuzhiyun depth = mode->RedMaskSize + mode->GreenMaskSize +
57*4882a593Smuzhiyun mode->BlueMaskSize;
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun else {
60*4882a593Smuzhiyun depth = 1;
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun bpp = mode->BitsPerPixel;
63*4882a593Smuzhiyun VBEFreeModeInfo(mode);
64*4882a593Smuzhiyun mode = NULL;
65*4882a593Smuzhiyun switch (depth) {
66*4882a593Smuzhiyun case 1:
67*4882a593Smuzhiyun return V_DEPTH_1;
68*4882a593Smuzhiyun case 4:
69*4882a593Smuzhiyun return V_DEPTH_4;
70*4882a593Smuzhiyun case 8:
71*4882a593Smuzhiyun return V_DEPTH_8;
72*4882a593Smuzhiyun case 15:
73*4882a593Smuzhiyun return V_DEPTH_15;
74*4882a593Smuzhiyun case 16:
75*4882a593Smuzhiyun return V_DEPTH_16;
76*4882a593Smuzhiyun case 24:
77*4882a593Smuzhiyun switch (bpp) {
78*4882a593Smuzhiyun case 24:
79*4882a593Smuzhiyun return V_DEPTH_24_24;
80*4882a593Smuzhiyun case 32:
81*4882a593Smuzhiyun return V_DEPTH_24_32;
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun if (mode)
86*4882a593Smuzhiyun VBEFreeModeInfo(mode);
87*4882a593Smuzhiyun return 0;
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun /*
91*4882a593Smuzhiyun * Find supported mode depths.
92*4882a593Smuzhiyun */
93*4882a593Smuzhiyun int
VBEFindSupportedDepths(vbeInfoPtr pVbe,VbeInfoBlock * vbe,int * flags24,int modeTypes)94*4882a593Smuzhiyun VBEFindSupportedDepths(vbeInfoPtr pVbe, VbeInfoBlock * vbe, int *flags24,
95*4882a593Smuzhiyun int modeTypes)
96*4882a593Smuzhiyun {
97*4882a593Smuzhiyun int i = 0;
98*4882a593Smuzhiyun int depths = 0;
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun if (modeTypes & V_MODETYPE_VBE) {
101*4882a593Smuzhiyun while (vbe->VideoModePtr[i] != 0xffff) {
102*4882a593Smuzhiyun depths |= GetDepthFlag(pVbe, vbe->VideoModePtr[i++]);
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun /*
107*4882a593Smuzhiyun * XXX This possibly only works with VBE 3.0 and later.
108*4882a593Smuzhiyun */
109*4882a593Smuzhiyun if (modeTypes & V_MODETYPE_VGA) {
110*4882a593Smuzhiyun for (i = 0; i < 0x7F; i++) {
111*4882a593Smuzhiyun depths |= GetDepthFlag(pVbe, i);
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun if (flags24) {
116*4882a593Smuzhiyun if (depths & V_DEPTH_24_24)
117*4882a593Smuzhiyun *flags24 |= Support24bppFb;
118*4882a593Smuzhiyun if (depths & V_DEPTH_24_32)
119*4882a593Smuzhiyun *flags24 |= Support32bppFb;
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun return depths;
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun static DisplayModePtr
CheckMode(ScrnInfoPtr pScrn,vbeInfoPtr pVbe,VbeInfoBlock * vbe,int id,int flags)126*4882a593Smuzhiyun CheckMode(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock * vbe, int id,
127*4882a593Smuzhiyun int flags)
128*4882a593Smuzhiyun {
129*4882a593Smuzhiyun CARD16 major;
130*4882a593Smuzhiyun VbeModeInfoBlock *mode;
131*4882a593Smuzhiyun DisplayModePtr pMode;
132*4882a593Smuzhiyun VbeModeInfoData *data;
133*4882a593Smuzhiyun Bool modeOK = FALSE;
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun major = (unsigned) (vbe->VESAVersion >> 8);
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun if ((mode = VBEGetModeInfo(pVbe, id)) == NULL)
138*4882a593Smuzhiyun return NULL;
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun /* Does the mode match the depth/bpp? */
141*4882a593Smuzhiyun /* Some BIOS's set BitsPerPixel to 15 instead of 16 for 15/16 */
142*4882a593Smuzhiyun if (VBE_MODE_USABLE(mode, flags) &&
143*4882a593Smuzhiyun ((pScrn->bitsPerPixel == 1 && !VBE_MODE_COLOR(mode)) ||
144*4882a593Smuzhiyun (mode->BitsPerPixel > 8 &&
145*4882a593Smuzhiyun (mode->RedMaskSize + mode->GreenMaskSize +
146*4882a593Smuzhiyun mode->BlueMaskSize) == pScrn->depth &&
147*4882a593Smuzhiyun mode->BitsPerPixel == pScrn->bitsPerPixel) ||
148*4882a593Smuzhiyun (mode->BitsPerPixel == 15 && pScrn->depth == 15) ||
149*4882a593Smuzhiyun (mode->BitsPerPixel <= 8 &&
150*4882a593Smuzhiyun mode->BitsPerPixel == pScrn->bitsPerPixel))) {
151*4882a593Smuzhiyun modeOK = TRUE;
152*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB, "*");
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB,
156*4882a593Smuzhiyun "Mode: %x (%dx%d)\n", id, mode->XResolution,
157*4882a593Smuzhiyun mode->YResolution);
158*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB, " ModeAttributes: 0x%x\n",
159*4882a593Smuzhiyun mode->ModeAttributes);
160*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB, " WinAAttributes: 0x%x\n",
161*4882a593Smuzhiyun mode->WinAAttributes);
162*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB, " WinBAttributes: 0x%x\n",
163*4882a593Smuzhiyun mode->WinBAttributes);
164*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB, " WinGranularity: %d\n",
165*4882a593Smuzhiyun mode->WinGranularity);
166*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB, " WinSize: %d\n", mode->WinSize);
167*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB,
168*4882a593Smuzhiyun " WinASegment: 0x%x\n", mode->WinASegment);
169*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB,
170*4882a593Smuzhiyun " WinBSegment: 0x%x\n", mode->WinBSegment);
171*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB,
172*4882a593Smuzhiyun " WinFuncPtr: 0x%lx\n", (unsigned long) mode->WinFuncPtr);
173*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB,
174*4882a593Smuzhiyun " BytesPerScanline: %d\n", mode->BytesPerScanline);
175*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB, " XResolution: %d\n", mode->XResolution);
176*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB, " YResolution: %d\n", mode->YResolution);
177*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB, " XCharSize: %d\n", mode->XCharSize);
178*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB, " YCharSize: %d\n", mode->YCharSize);
179*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB,
180*4882a593Smuzhiyun " NumberOfPlanes: %d\n", mode->NumberOfPlanes);
181*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB,
182*4882a593Smuzhiyun " BitsPerPixel: %d\n", mode->BitsPerPixel);
183*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB,
184*4882a593Smuzhiyun " NumberOfBanks: %d\n", mode->NumberOfBanks);
185*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB, " MemoryModel: %d\n", mode->MemoryModel);
186*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB, " BankSize: %d\n", mode->BankSize);
187*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB,
188*4882a593Smuzhiyun " NumberOfImages: %d\n", mode->NumberOfImages);
189*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB, " RedMaskSize: %d\n", mode->RedMaskSize);
190*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB,
191*4882a593Smuzhiyun " RedFieldPosition: %d\n", mode->RedFieldPosition);
192*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB,
193*4882a593Smuzhiyun " GreenMaskSize: %d\n", mode->GreenMaskSize);
194*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB,
195*4882a593Smuzhiyun " GreenFieldPosition: %d\n", mode->GreenFieldPosition);
196*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB,
197*4882a593Smuzhiyun " BlueMaskSize: %d\n", mode->BlueMaskSize);
198*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB,
199*4882a593Smuzhiyun " BlueFieldPosition: %d\n", mode->BlueFieldPosition);
200*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB,
201*4882a593Smuzhiyun " RsvdMaskSize: %d\n", mode->RsvdMaskSize);
202*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB,
203*4882a593Smuzhiyun " RsvdFieldPosition: %d\n", mode->RsvdFieldPosition);
204*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB,
205*4882a593Smuzhiyun " DirectColorModeInfo: %d\n", mode->DirectColorModeInfo);
206*4882a593Smuzhiyun if (major >= 2) {
207*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB,
208*4882a593Smuzhiyun " PhysBasePtr: 0x%lx\n",
209*4882a593Smuzhiyun (unsigned long) mode->PhysBasePtr);
210*4882a593Smuzhiyun if (major >= 3) {
211*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB,
212*4882a593Smuzhiyun " LinBytesPerScanLine: %d\n",
213*4882a593Smuzhiyun mode->LinBytesPerScanLine);
214*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB, " BnkNumberOfImagePages: %d\n",
215*4882a593Smuzhiyun mode->BnkNumberOfImagePages);
216*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB, " LinNumberOfImagePages: %d\n",
217*4882a593Smuzhiyun mode->LinNumberOfImagePages);
218*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB, " LinRedMaskSize: %d\n",
219*4882a593Smuzhiyun mode->LinRedMaskSize);
220*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB, " LinRedFieldPosition: %d\n",
221*4882a593Smuzhiyun mode->LinRedFieldPosition);
222*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB, " LinGreenMaskSize: %d\n",
223*4882a593Smuzhiyun mode->LinGreenMaskSize);
224*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB, " LinGreenFieldPosition: %d\n",
225*4882a593Smuzhiyun mode->LinGreenFieldPosition);
226*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB, " LinBlueMaskSize: %d\n",
227*4882a593Smuzhiyun mode->LinBlueMaskSize);
228*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB, " LinBlueFieldPosition: %d\n",
229*4882a593Smuzhiyun mode->LinBlueFieldPosition);
230*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB, " LinRsvdMaskSize: %d\n",
231*4882a593Smuzhiyun mode->LinRsvdMaskSize);
232*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB, " LinRsvdFieldPosition: %d\n",
233*4882a593Smuzhiyun mode->LinRsvdFieldPosition);
234*4882a593Smuzhiyun xf86ErrorFVerb(DEBUG_VERB, " MaxPixelClock: %ld\n",
235*4882a593Smuzhiyun (unsigned long) mode->MaxPixelClock);
236*4882a593Smuzhiyun }
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun if (!modeOK) {
240*4882a593Smuzhiyun VBEFreeModeInfo(mode);
241*4882a593Smuzhiyun return NULL;
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun pMode = xnfcalloc(sizeof(DisplayModeRec), 1);
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun pMode->status = MODE_OK;
246*4882a593Smuzhiyun pMode->type = M_T_BUILTIN;
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun /* for adjust frame */
249*4882a593Smuzhiyun pMode->HDisplay = mode->XResolution;
250*4882a593Smuzhiyun pMode->VDisplay = mode->YResolution;
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun data = xnfcalloc(sizeof(VbeModeInfoData), 1);
253*4882a593Smuzhiyun data->mode = id;
254*4882a593Smuzhiyun data->data = mode;
255*4882a593Smuzhiyun pMode->PrivSize = sizeof(VbeModeInfoData);
256*4882a593Smuzhiyun pMode->Private = (INT32 *) data;
257*4882a593Smuzhiyun pMode->next = NULL;
258*4882a593Smuzhiyun return pMode;
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun /*
262*4882a593Smuzhiyun * Check the available BIOS modes, and extract those that match the
263*4882a593Smuzhiyun * requirements into the modePool. Note: modePool is a NULL-terminated
264*4882a593Smuzhiyun * list.
265*4882a593Smuzhiyun */
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun DisplayModePtr
VBEGetModePool(ScrnInfoPtr pScrn,vbeInfoPtr pVbe,VbeInfoBlock * vbe,int modeTypes)268*4882a593Smuzhiyun VBEGetModePool(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock * vbe,
269*4882a593Smuzhiyun int modeTypes)
270*4882a593Smuzhiyun {
271*4882a593Smuzhiyun DisplayModePtr pMode, p = NULL, modePool = NULL;
272*4882a593Smuzhiyun int i = 0;
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun if (modeTypes & V_MODETYPE_VBE) {
275*4882a593Smuzhiyun while (vbe->VideoModePtr[i] != 0xffff) {
276*4882a593Smuzhiyun int id = vbe->VideoModePtr[i++];
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun if ((pMode = CheckMode(pScrn, pVbe, vbe, id, modeTypes)) != NULL) {
279*4882a593Smuzhiyun ModeStatus status = MODE_OK;
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun /* Check the mode against a specified virtual size (if any) */
282*4882a593Smuzhiyun if (pScrn->display->virtualX > 0 &&
283*4882a593Smuzhiyun pMode->HDisplay > pScrn->display->virtualX) {
284*4882a593Smuzhiyun status = MODE_VIRTUAL_X;
285*4882a593Smuzhiyun }
286*4882a593Smuzhiyun if (pScrn->display->virtualY > 0 &&
287*4882a593Smuzhiyun pMode->VDisplay > pScrn->display->virtualY) {
288*4882a593Smuzhiyun status = MODE_VIRTUAL_Y;
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun if (status != MODE_OK) {
291*4882a593Smuzhiyun xf86DrvMsg(pScrn->scrnIndex, X_INFO,
292*4882a593Smuzhiyun "Not using mode \"%dx%d\" (%s)\n",
293*4882a593Smuzhiyun pMode->HDisplay, pMode->VDisplay,
294*4882a593Smuzhiyun xf86ModeStatusToString(status));
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun else {
297*4882a593Smuzhiyun if (p == NULL) {
298*4882a593Smuzhiyun modePool = pMode;
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun else {
301*4882a593Smuzhiyun p->next = pMode;
302*4882a593Smuzhiyun }
303*4882a593Smuzhiyun pMode->prev = NULL;
304*4882a593Smuzhiyun p = pMode;
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun }
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun if (modeTypes & V_MODETYPE_VGA) {
310*4882a593Smuzhiyun for (i = 0; i < 0x7F; i++) {
311*4882a593Smuzhiyun if ((pMode = CheckMode(pScrn, pVbe, vbe, i, modeTypes)) != NULL) {
312*4882a593Smuzhiyun ModeStatus status = MODE_OK;
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun /* Check the mode against a specified virtual size (if any) */
315*4882a593Smuzhiyun if (pScrn->display->virtualX > 0 &&
316*4882a593Smuzhiyun pMode->HDisplay > pScrn->display->virtualX) {
317*4882a593Smuzhiyun status = MODE_VIRTUAL_X;
318*4882a593Smuzhiyun }
319*4882a593Smuzhiyun if (pScrn->display->virtualY > 0 &&
320*4882a593Smuzhiyun pMode->VDisplay > pScrn->display->virtualY) {
321*4882a593Smuzhiyun status = MODE_VIRTUAL_Y;
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun if (status != MODE_OK) {
324*4882a593Smuzhiyun xf86DrvMsg(pScrn->scrnIndex, X_INFO,
325*4882a593Smuzhiyun "Not using mode \"%dx%d\" (%s)\n",
326*4882a593Smuzhiyun pMode->HDisplay, pMode->VDisplay,
327*4882a593Smuzhiyun xf86ModeStatusToString(status));
328*4882a593Smuzhiyun }
329*4882a593Smuzhiyun else {
330*4882a593Smuzhiyun if (p == NULL) {
331*4882a593Smuzhiyun modePool = pMode;
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun else {
334*4882a593Smuzhiyun p->next = pMode;
335*4882a593Smuzhiyun }
336*4882a593Smuzhiyun pMode->prev = NULL;
337*4882a593Smuzhiyun p = pMode;
338*4882a593Smuzhiyun }
339*4882a593Smuzhiyun }
340*4882a593Smuzhiyun }
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun return modePool;
343*4882a593Smuzhiyun }
344*4882a593Smuzhiyun
345*4882a593Smuzhiyun void
VBESetModeNames(DisplayModePtr pMode)346*4882a593Smuzhiyun VBESetModeNames(DisplayModePtr pMode)
347*4882a593Smuzhiyun {
348*4882a593Smuzhiyun if (!pMode)
349*4882a593Smuzhiyun return;
350*4882a593Smuzhiyun
351*4882a593Smuzhiyun do {
352*4882a593Smuzhiyun if (!pMode->name) {
353*4882a593Smuzhiyun /* Catch "bad" modes. */
354*4882a593Smuzhiyun if (pMode->HDisplay > 10000 || pMode->HDisplay < 0 ||
355*4882a593Smuzhiyun pMode->VDisplay > 10000 || pMode->VDisplay < 0) {
356*4882a593Smuzhiyun pMode->name = strdup("BADMODE");
357*4882a593Smuzhiyun }
358*4882a593Smuzhiyun else {
359*4882a593Smuzhiyun char *tmp;
360*4882a593Smuzhiyun XNFasprintf(&tmp, "%dx%d",
361*4882a593Smuzhiyun pMode->HDisplay, pMode->VDisplay);
362*4882a593Smuzhiyun pMode->name = tmp;
363*4882a593Smuzhiyun }
364*4882a593Smuzhiyun }
365*4882a593Smuzhiyun pMode = pMode->next;
366*4882a593Smuzhiyun } while (pMode);
367*4882a593Smuzhiyun }
368*4882a593Smuzhiyun
369*4882a593Smuzhiyun /*
370*4882a593Smuzhiyun * Go through the monitor modes and selecting the best set of
371*4882a593Smuzhiyun * parameters for each BIOS mode. Note: This is only supported in
372*4882a593Smuzhiyun * VBE version 3.0 or later.
373*4882a593Smuzhiyun */
374*4882a593Smuzhiyun void
VBESetModeParameters(ScrnInfoPtr pScrn,vbeInfoPtr pVbe)375*4882a593Smuzhiyun VBESetModeParameters(ScrnInfoPtr pScrn, vbeInfoPtr pVbe)
376*4882a593Smuzhiyun {
377*4882a593Smuzhiyun DisplayModePtr pMode;
378*4882a593Smuzhiyun VbeModeInfoData *data;
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun pMode = pScrn->modes;
381*4882a593Smuzhiyun do {
382*4882a593Smuzhiyun DisplayModePtr p, best = NULL;
383*4882a593Smuzhiyun ModeStatus status;
384*4882a593Smuzhiyun
385*4882a593Smuzhiyun for (p = pScrn->monitor->Modes; p != NULL; p = p->next) {
386*4882a593Smuzhiyun if ((p->HDisplay != pMode->HDisplay) ||
387*4882a593Smuzhiyun (p->VDisplay != pMode->VDisplay) ||
388*4882a593Smuzhiyun (p->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2)))
389*4882a593Smuzhiyun continue;
390*4882a593Smuzhiyun /* XXX could support the various V_ flags */
391*4882a593Smuzhiyun status = xf86CheckModeForMonitor(p, pScrn->monitor);
392*4882a593Smuzhiyun if (status != MODE_OK)
393*4882a593Smuzhiyun continue;
394*4882a593Smuzhiyun if (!best || (p->Clock > best->Clock))
395*4882a593Smuzhiyun best = p;
396*4882a593Smuzhiyun }
397*4882a593Smuzhiyun
398*4882a593Smuzhiyun if (best) {
399*4882a593Smuzhiyun int clock;
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun data = (VbeModeInfoData *) pMode->Private;
402*4882a593Smuzhiyun pMode->HSync = (float) best->Clock * 1000.0 / best->HTotal + 0.5;
403*4882a593Smuzhiyun pMode->VRefresh = pMode->HSync / best->VTotal + 0.5;
404*4882a593Smuzhiyun xf86DrvMsg(pScrn->scrnIndex, X_INFO,
405*4882a593Smuzhiyun "Attempting to use %dHz refresh for mode \"%s\" (%x)\n",
406*4882a593Smuzhiyun (int) pMode->VRefresh, pMode->name, data->mode);
407*4882a593Smuzhiyun data->block = calloc(sizeof(VbeCRTCInfoBlock), 1);
408*4882a593Smuzhiyun data->block->HorizontalTotal = best->HTotal;
409*4882a593Smuzhiyun data->block->HorizontalSyncStart = best->HSyncStart;
410*4882a593Smuzhiyun data->block->HorizontalSyncEnd = best->HSyncEnd;
411*4882a593Smuzhiyun data->block->VerticalTotal = best->VTotal;
412*4882a593Smuzhiyun data->block->VerticalSyncStart = best->VSyncStart;
413*4882a593Smuzhiyun data->block->VerticalSyncEnd = best->VSyncEnd;
414*4882a593Smuzhiyun data->block->Flags = ((best->Flags & V_NHSYNC) ? CRTC_NHSYNC : 0) |
415*4882a593Smuzhiyun ((best->Flags & V_NVSYNC) ? CRTC_NVSYNC : 0);
416*4882a593Smuzhiyun data->block->PixelClock = best->Clock * 1000;
417*4882a593Smuzhiyun /* XXX May not have this. */
418*4882a593Smuzhiyun clock = VBEGetPixelClock(pVbe, data->mode, data->block->PixelClock);
419*4882a593Smuzhiyun DebugF("Setting clock %.2fMHz, closest is %.2fMHz\n",
420*4882a593Smuzhiyun (double) data->block->PixelClock / 1000000.0,
421*4882a593Smuzhiyun (double) clock / 1000000.0);
422*4882a593Smuzhiyun if (clock)
423*4882a593Smuzhiyun data->block->PixelClock = clock;
424*4882a593Smuzhiyun data->mode |= (1 << 11);
425*4882a593Smuzhiyun data->block->RefreshRate = ((double) (data->block->PixelClock) /
426*4882a593Smuzhiyun (double) (best->HTotal *
427*4882a593Smuzhiyun best->VTotal)) * 100;
428*4882a593Smuzhiyun }
429*4882a593Smuzhiyun pMode = pMode->next;
430*4882a593Smuzhiyun } while (pMode != pScrn->modes);
431*4882a593Smuzhiyun }
432*4882a593Smuzhiyun
433*4882a593Smuzhiyun /*
434*4882a593Smuzhiyun * These wrappers are to allow (temporary) funtionality divergences.
435*4882a593Smuzhiyun */
436*4882a593Smuzhiyun int
VBEValidateModes(ScrnInfoPtr scrp,DisplayModePtr availModes,const char ** modeNames,ClockRangePtr clockRanges,int * linePitches,int minPitch,int maxPitch,int pitchInc,int minHeight,int maxHeight,int virtualX,int virtualY,int apertureSize,LookupModeFlags strategy)437*4882a593Smuzhiyun VBEValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes,
438*4882a593Smuzhiyun const char **modeNames, ClockRangePtr clockRanges,
439*4882a593Smuzhiyun int *linePitches, int minPitch, int maxPitch, int pitchInc,
440*4882a593Smuzhiyun int minHeight, int maxHeight, int virtualX, int virtualY,
441*4882a593Smuzhiyun int apertureSize, LookupModeFlags strategy)
442*4882a593Smuzhiyun {
443*4882a593Smuzhiyun return xf86ValidateModes(scrp, availModes, modeNames, clockRanges,
444*4882a593Smuzhiyun linePitches, minPitch, maxPitch, pitchInc,
445*4882a593Smuzhiyun minHeight, maxHeight, virtualX, virtualY,
446*4882a593Smuzhiyun apertureSize, strategy);
447*4882a593Smuzhiyun }
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun void
VBEPrintModes(ScrnInfoPtr scrp)450*4882a593Smuzhiyun VBEPrintModes(ScrnInfoPtr scrp)
451*4882a593Smuzhiyun {
452*4882a593Smuzhiyun xf86PrintModes(scrp);
453*4882a593Smuzhiyun }
454