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 43static int 44GetDepthFlag(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 } else { 59 depth = 1; 60 } 61 bpp = mode->BitsPerPixel; 62 VBEFreeModeInfo(mode); 63 mode = NULL; 64 switch (depth) { 65 case 1: 66 return V_DEPTH_1; 67 case 4: 68 return V_DEPTH_4; 69 case 8: 70 return V_DEPTH_8; 71 case 15: 72 return V_DEPTH_15; 73 case 16: 74 return V_DEPTH_16; 75 case 24: 76 switch (bpp) { 77 case 24: 78 return V_DEPTH_24_24; 79 case 32: 80 return V_DEPTH_24_32; 81 } 82 } 83 } 84 if (mode) 85 VBEFreeModeInfo(mode); 86 return 0; 87} 88 89/* 90 * Find supported mode depths. 91 */ 92int 93VBEFindSupportedDepths(vbeInfoPtr pVbe, VbeInfoBlock *vbe, int *flags24, 94 int modeTypes) 95{ 96 int i = 0; 97 int depths = 0; 98 99 if (modeTypes & V_MODETYPE_VBE) { 100 while (vbe->VideoModePtr[i] != 0xffff) { 101 depths |= GetDepthFlag(pVbe, vbe->VideoModePtr[i++]); 102 } 103 } 104 105 /* 106 * XXX This possibly only works with VBE 3.0 and later. 107 */ 108 if (modeTypes & V_MODETYPE_VGA) { 109 for (i = 0; i < 0x7F; i++) { 110 depths |= GetDepthFlag(pVbe, i); 111 } 112 } 113 114 if (flags24) { 115 if (depths & V_DEPTH_24_24) 116 *flags24 |= Support24bppFb; 117 if (depths & V_DEPTH_24_32) 118 *flags24 |= Support32bppFb; 119 } 120 121 return depths; 122} 123 124static DisplayModePtr 125CheckMode(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock *vbe, int id, 126 int flags) 127{ 128 CARD16 major; 129 VbeModeInfoBlock *mode; 130 DisplayModePtr pMode; 131 VbeModeInfoData *data; 132 Bool modeOK = FALSE; 133 134 major = (unsigned)(vbe->VESAVersion >> 8); 135 136 if ((mode = VBEGetModeInfo(pVbe, id)) == NULL) 137 return NULL; 138 139 /* Does the mode match the depth/bpp? */ 140 /* Some BIOS's set BitsPerPixel to 15 instead of 16 for 15/16 */ 141 if (VBE_MODE_USABLE(mode, flags) && 142 ((pScrn->bitsPerPixel == 1 && !VBE_MODE_COLOR(mode)) || 143 (mode->BitsPerPixel > 8 && 144 (mode->RedMaskSize + mode->GreenMaskSize + 145 mode->BlueMaskSize) == pScrn->depth && 146 mode->BitsPerPixel == pScrn->bitsPerPixel) || 147 (mode->BitsPerPixel == 15 && pScrn->depth == 15) || 148 (mode->BitsPerPixel <= 8 && 149 mode->BitsPerPixel == pScrn->bitsPerPixel))) { 150 modeOK = TRUE; 151 xf86ErrorFVerb(DEBUG_VERB, "*"); 152 } 153 154 xf86ErrorFVerb(DEBUG_VERB, 155 "Mode: %x (%dx%d)\n", id, mode->XResolution, mode->YResolution); 156 xf86ErrorFVerb(DEBUG_VERB, 157 " ModeAttributes: 0x%x\n", mode->ModeAttributes); 158 xf86ErrorFVerb(DEBUG_VERB, 159 " WinAAttributes: 0x%x\n", mode->WinAAttributes); 160 xf86ErrorFVerb(DEBUG_VERB, 161 " WinBAttributes: 0x%x\n", mode->WinBAttributes); 162 xf86ErrorFVerb(DEBUG_VERB, 163 " WinGranularity: %d\n", mode->WinGranularity); 164 xf86ErrorFVerb(DEBUG_VERB, 165 " WinSize: %d\n", mode->WinSize); 166 xf86ErrorFVerb(DEBUG_VERB, 167 " WinASegment: 0x%x\n", mode->WinASegment); 168 xf86ErrorFVerb(DEBUG_VERB, 169 " WinBSegment: 0x%x\n", mode->WinBSegment); 170 xf86ErrorFVerb(DEBUG_VERB, 171 " WinFuncPtr: 0x%lx\n", (unsigned long)mode->WinFuncPtr); 172 xf86ErrorFVerb(DEBUG_VERB, 173 " BytesPerScanline: %d\n", mode->BytesPerScanline); 174 xf86ErrorFVerb(DEBUG_VERB, 175 " XResolution: %d\n", mode->XResolution); 176 xf86ErrorFVerb(DEBUG_VERB, 177 " YResolution: %d\n", mode->YResolution); 178 xf86ErrorFVerb(DEBUG_VERB, 179 " XCharSize: %d\n", mode->XCharSize); 180 xf86ErrorFVerb(DEBUG_VERB, 181 " YCharSize: %d\n", mode->YCharSize); 182 xf86ErrorFVerb(DEBUG_VERB, 183 " NumberOfPlanes: %d\n", mode->NumberOfPlanes); 184 xf86ErrorFVerb(DEBUG_VERB, 185 " BitsPerPixel: %d\n", mode->BitsPerPixel); 186 xf86ErrorFVerb(DEBUG_VERB, 187 " NumberOfBanks: %d\n", mode->NumberOfBanks); 188 xf86ErrorFVerb(DEBUG_VERB, 189 " MemoryModel: %d\n", mode->MemoryModel); 190 xf86ErrorFVerb(DEBUG_VERB, 191 " BankSize: %d\n", mode->BankSize); 192 xf86ErrorFVerb(DEBUG_VERB, 193 " NumberOfImages: %d\n", mode->NumberOfImages); 194 xf86ErrorFVerb(DEBUG_VERB, 195 " RedMaskSize: %d\n", mode->RedMaskSize); 196 xf86ErrorFVerb(DEBUG_VERB, 197 " RedFieldPosition: %d\n", mode->RedFieldPosition); 198 xf86ErrorFVerb(DEBUG_VERB, 199 " GreenMaskSize: %d\n", mode->GreenMaskSize); 200 xf86ErrorFVerb(DEBUG_VERB, 201 " GreenFieldPosition: %d\n", mode->GreenFieldPosition); 202 xf86ErrorFVerb(DEBUG_VERB, 203 " BlueMaskSize: %d\n", mode->BlueMaskSize); 204 xf86ErrorFVerb(DEBUG_VERB, 205 " BlueFieldPosition: %d\n", mode->BlueFieldPosition); 206 xf86ErrorFVerb(DEBUG_VERB, 207 " RsvdMaskSize: %d\n", mode->RsvdMaskSize); 208 xf86ErrorFVerb(DEBUG_VERB, 209 " RsvdFieldPosition: %d\n", mode->RsvdFieldPosition); 210 xf86ErrorFVerb(DEBUG_VERB, 211 " DirectColorModeInfo: %d\n", mode->DirectColorModeInfo); 212 if (major >= 2) { 213 xf86ErrorFVerb(DEBUG_VERB, 214 " PhysBasePtr: 0x%lx\n", 215 (unsigned long)mode->PhysBasePtr); 216 if (major >= 3) { 217 xf86ErrorFVerb(DEBUG_VERB, 218 " LinBytesPerScanLine: %d\n", mode->LinBytesPerScanLine); 219 xf86ErrorFVerb(DEBUG_VERB, 220 " BnkNumberOfImagePages: %d\n", mode->BnkNumberOfImagePages); 221 xf86ErrorFVerb(DEBUG_VERB, 222 " LinNumberOfImagePages: %d\n", mode->LinNumberOfImagePages); 223 xf86ErrorFVerb(DEBUG_VERB, 224 " LinRedMaskSize: %d\n", mode->LinRedMaskSize); 225 xf86ErrorFVerb(DEBUG_VERB, 226 " LinRedFieldPosition: %d\n", mode->LinRedFieldPosition); 227 xf86ErrorFVerb(DEBUG_VERB, 228 " LinGreenMaskSize: %d\n", mode->LinGreenMaskSize); 229 xf86ErrorFVerb(DEBUG_VERB, 230 " LinGreenFieldPosition: %d\n", mode->LinGreenFieldPosition); 231 xf86ErrorFVerb(DEBUG_VERB, 232 " LinBlueMaskSize: %d\n", mode->LinBlueMaskSize); 233 xf86ErrorFVerb(DEBUG_VERB, 234 " LinBlueFieldPosition: %d\n", mode->LinBlueFieldPosition); 235 xf86ErrorFVerb(DEBUG_VERB, 236 " LinRsvdMaskSize: %d\n", mode->LinRsvdMaskSize); 237 xf86ErrorFVerb(DEBUG_VERB, 238 " LinRsvdFieldPosition: %d\n", mode->LinRsvdFieldPosition); 239 xf86ErrorFVerb(DEBUG_VERB, 240 " MaxPixelClock: %ld\n", (unsigned long)mode->MaxPixelClock); 241 } 242 } 243 244 if (!modeOK) { 245 VBEFreeModeInfo(mode); 246 return NULL; 247 } 248 pMode = xnfcalloc(sizeof(DisplayModeRec), 1); 249 250 pMode->status = MODE_OK; 251 pMode->type = M_T_BUILTIN; 252 253 /* for adjust frame */ 254 pMode->HDisplay = mode->XResolution; 255 pMode->VDisplay = mode->YResolution; 256 257 data = xnfcalloc(sizeof(VbeModeInfoData), 1); 258 data->mode = id; 259 data->data = mode; 260 pMode->PrivSize = sizeof(VbeModeInfoData); 261 pMode->Private = (INT32*)data; 262 pMode->next = NULL; 263 return pMode; 264} 265 266/* 267 * Check the available BIOS modes, and extract those that match the 268 * requirements into the modePool. Note: modePool is a NULL-terminated 269 * list. 270 */ 271 272DisplayModePtr 273VBEGetModePool(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock *vbe, 274 int modeTypes) 275{ 276 DisplayModePtr pMode, p = NULL, modePool = NULL; 277 int i = 0; 278 279 if (modeTypes & V_MODETYPE_VBE) { 280 while (vbe->VideoModePtr[i] != 0xffff) { 281 int id = vbe->VideoModePtr[i++]; 282 283 if ((pMode = CheckMode(pScrn, pVbe, vbe, id, modeTypes)) != NULL) { 284 ModeStatus status = MODE_OK; 285 286 /* Check the mode against a specified virtual size (if any) */ 287 if (pScrn->display->virtualX > 0 && 288 pMode->HDisplay > pScrn->display->virtualX) { 289 status = MODE_VIRTUAL_X; 290 } 291 if (pScrn->display->virtualY > 0 && 292 pMode->VDisplay > pScrn->display->virtualY) { 293 status = MODE_VIRTUAL_Y; 294 } 295 if (status != MODE_OK) { 296 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 297 "Not using mode \"%dx%d\" (%s)\n", 298 pMode->HDisplay, pMode->VDisplay, 299 xf86ModeStatusToString(status)); 300 } else { 301 if (p == NULL) { 302 modePool = pMode; 303 } else { 304 p->next = pMode; 305 } 306 pMode->prev = NULL; 307 p = pMode; 308 } 309 } 310 } 311 } 312 if (modeTypes & V_MODETYPE_VGA) { 313 for (i = 0; i < 0x7F; i++) { 314 if ((pMode = CheckMode(pScrn, pVbe, vbe, i, modeTypes)) != NULL) { 315 ModeStatus status = MODE_OK; 316 317 /* Check the mode against a specified virtual size (if any) */ 318 if (pScrn->display->virtualX > 0 && 319 pMode->HDisplay > pScrn->display->virtualX) { 320 status = MODE_VIRTUAL_X; 321 } 322 if (pScrn->display->virtualY > 0 && 323 pMode->VDisplay > pScrn->display->virtualY) { 324 status = MODE_VIRTUAL_Y; 325 } 326 if (status != MODE_OK) { 327 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 328 "Not using mode \"%dx%d\" (%s)\n", 329 pMode->HDisplay, pMode->VDisplay, 330 xf86ModeStatusToString(status)); 331 } else { 332 if (p == NULL) { 333 modePool = pMode; 334 } else { 335 p->next = pMode; 336 } 337 pMode->prev = NULL; 338 p = pMode; 339 } 340 } 341 } 342 } 343 return modePool; 344} 345 346void 347VBESetModeNames(DisplayModePtr pMode) 348{ 349 if (!pMode) 350 return; 351 352 do { 353 if (!pMode->name) { 354 /* Catch "bad" modes. */ 355 if (pMode->HDisplay > 10000 || pMode->HDisplay < 0 || 356 pMode->VDisplay > 10000 || pMode->VDisplay < 0) { 357 pMode->name = strdup("BADMODE"); 358 } else { 359 XNFasprintf(&pMode->name, "%dx%d", 360 pMode->HDisplay, pMode->VDisplay); 361 } 362 } 363 pMode = pMode->next; 364 } while (pMode); 365} 366 367/* 368 * Go through the monitor modes and selecting the best set of 369 * parameters for each BIOS mode. Note: This is only supported in 370 * VBE version 3.0 or later. 371 */ 372void 373VBESetModeParameters(ScrnInfoPtr pScrn, vbeInfoPtr pVbe) 374{ 375 DisplayModePtr pMode; 376 VbeModeInfoData *data; 377 378 pMode = pScrn->modes; 379 do { 380 DisplayModePtr p, best = NULL; 381 ModeStatus status; 382 383 for (p = pScrn->monitor->Modes; p != NULL; p = p->next) { 384 if ((p->HDisplay != pMode->HDisplay) || 385 (p->VDisplay != pMode->VDisplay) || 386 (p->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2))) 387 continue; 388 /* XXX could support the various V_ flags */ 389 status = xf86CheckModeForMonitor(p, pScrn->monitor); 390 if (status != MODE_OK) 391 continue; 392 if (!best || (p->Clock > best->Clock)) 393 best = p; 394 } 395 396 if (best) { 397 int clock; 398 399 data = (VbeModeInfoData*)pMode->Private; 400 pMode->HSync = (float)best->Clock * 1000.0 / best->HTotal + 0.5; 401 pMode->VRefresh = pMode->HSync / best->VTotal + 0.5; 402 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 403 "Attempting to use %dHz refresh for mode \"%s\" (%x)\n", 404 (int)pMode->VRefresh, pMode->name, data->mode); 405 data->block = calloc(sizeof(VbeCRTCInfoBlock), 1); 406 data->block->HorizontalTotal = best->HTotal; 407 data->block->HorizontalSyncStart = best->HSyncStart; 408 data->block->HorizontalSyncEnd = best->HSyncEnd; 409 data->block->VerticalTotal = best->VTotal; 410 data->block->VerticalSyncStart = best->VSyncStart; 411 data->block->VerticalSyncEnd = best->VSyncEnd; 412 data->block->Flags = ((best->Flags & V_NHSYNC) ? CRTC_NHSYNC : 0) | 413 ((best->Flags & V_NVSYNC) ? CRTC_NVSYNC : 0); 414 data->block->PixelClock = best->Clock * 1000; 415 /* XXX May not have this. */ 416 clock = VBEGetPixelClock(pVbe, data->mode, data->block->PixelClock); 417 DebugF("Setting clock %.2fMHz, closest is %.2fMHz\n", 418 (double)data->block->PixelClock / 1000000.0, 419 (double)clock / 1000000.0); 420 if (clock) 421 data->block->PixelClock = clock; 422 data->mode |= (1 << 11); 423 data->block->RefreshRate = ((double)(data->block->PixelClock) / 424 (double)(best->HTotal * best->VTotal)) * 100; 425 } 426 pMode = pMode->next; 427 } while (pMode != pScrn->modes); 428} 429 430/* 431 * These wrappers are to allow (temporary) funtionality divergences. 432 */ 433int 434VBEValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes, 435 const char **modeNames, ClockRangePtr clockRanges, 436 int *linePitches, int minPitch, int maxPitch, int pitchInc, 437 int minHeight, int maxHeight, int virtualX, int virtualY, 438 int apertureSize, LookupModeFlags strategy) 439{ 440 return xf86ValidateModes(scrp, availModes, modeNames, clockRanges, 441 linePitches, minPitch, maxPitch, pitchInc, 442 minHeight, maxHeight, virtualX, virtualY, 443 apertureSize, strategy); 444} 445 446void 447VBEPrintModes(ScrnInfoPtr scrp) 448{ 449 xf86PrintModes(scrp); 450} 451 452