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