#define DEBUG_VERB 2
#ifdef HAVE_XORG_CONFIG_H
#include <xorg-config.h>
#endif
#include <stdio.h>
#include <string.h>
#include "xf86.h"
#include "vbe.h"
#include "vbeModes.h"
static int
GetDepthFlag(vbeInfoPtr pVbe, int id)
{
VbeModeInfoBlock *mode;
int bpp;
if ((mode = VBEGetModeInfo(pVbe, id)) == NULL)
return 0;
if (VBE_MODE_USABLE(mode, 0)) {
int depth;
if (VBE_MODE_COLOR(mode)) {
depth = mode->RedMaskSize + mode->GreenMaskSize +
mode->BlueMaskSize;
} else {
depth = 1;
}
bpp = mode->BitsPerPixel;
VBEFreeModeInfo(mode);
mode = NULL;
switch (depth) {
case 1:
return V_DEPTH_1;
case 4:
return V_DEPTH_4;
case 8:
return V_DEPTH_8;
case 15:
return V_DEPTH_15;
case 16:
return V_DEPTH_16;
case 24:
switch (bpp) {
case 24:
return V_DEPTH_24_24;
case 32:
return V_DEPTH_24_32;
}
}
}
if (mode)
VBEFreeModeInfo(mode);
return 0;
}
int
VBEFindSupportedDepths(vbeInfoPtr pVbe, VbeInfoBlock *vbe, int *flags24,
int modeTypes)
{
int i = 0;
int depths = 0;
if (modeTypes & V_MODETYPE_VBE) {
while (vbe->VideoModePtr[i] != 0xffff) {
depths |= GetDepthFlag(pVbe, vbe->VideoModePtr[i++]);
}
}
if (modeTypes & V_MODETYPE_VGA) {
for (i = 0; i < 0x7F; i++) {
depths |= GetDepthFlag(pVbe, i);
}
}
if (flags24) {
if (depths & V_DEPTH_24_24)
*flags24 |= Support24bppFb;
if (depths & V_DEPTH_24_32)
*flags24 |= Support32bppFb;
}
return depths;
}
static DisplayModePtr
CheckMode(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock *vbe, int id,
int flags)
{
CARD16 major;
VbeModeInfoBlock *mode;
DisplayModePtr pMode;
VbeModeInfoData *data;
Bool modeOK = FALSE;
major = (unsigned)(vbe->VESAVersion >> 8);
if ((mode = VBEGetModeInfo(pVbe, id)) == NULL)
return NULL;
if (VBE_MODE_USABLE(mode, flags) &&
((pScrn->bitsPerPixel == 1 && !VBE_MODE_COLOR(mode)) ||
(mode->BitsPerPixel > 8 &&
(mode->RedMaskSize + mode->GreenMaskSize +
mode->BlueMaskSize) == pScrn->depth &&
mode->BitsPerPixel == pScrn->bitsPerPixel) ||
(mode->BitsPerPixel == 15 && pScrn->depth == 15) ||
(mode->BitsPerPixel <= 8 &&
mode->BitsPerPixel == pScrn->bitsPerPixel))) {
modeOK = TRUE;
xf86ErrorFVerb(DEBUG_VERB, "*");
}
xf86ErrorFVerb(DEBUG_VERB,
"Mode: %x (%dx%d)\n", id, mode->XResolution, mode->YResolution);
xf86ErrorFVerb(DEBUG_VERB,
" ModeAttributes: 0x%x\n", mode->ModeAttributes);
xf86ErrorFVerb(DEBUG_VERB,
" WinAAttributes: 0x%x\n", mode->WinAAttributes);
xf86ErrorFVerb(DEBUG_VERB,
" WinBAttributes: 0x%x\n", mode->WinBAttributes);
xf86ErrorFVerb(DEBUG_VERB,
" WinGranularity: %d\n", mode->WinGranularity);
xf86ErrorFVerb(DEBUG_VERB,
" WinSize: %d\n", mode->WinSize);
xf86ErrorFVerb(DEBUG_VERB,
" WinASegment: 0x%x\n", mode->WinASegment);
xf86ErrorFVerb(DEBUG_VERB,
" WinBSegment: 0x%x\n", mode->WinBSegment);
xf86ErrorFVerb(DEBUG_VERB,
" WinFuncPtr: 0x%lx\n", (unsigned long)mode->WinFuncPtr);
xf86ErrorFVerb(DEBUG_VERB,
" BytesPerScanline: %d\n", mode->BytesPerScanline);
xf86ErrorFVerb(DEBUG_VERB,
" XResolution: %d\n", mode->XResolution);
xf86ErrorFVerb(DEBUG_VERB,
" YResolution: %d\n", mode->YResolution);
xf86ErrorFVerb(DEBUG_VERB,
" XCharSize: %d\n", mode->XCharSize);
xf86ErrorFVerb(DEBUG_VERB,
" YCharSize: %d\n", mode->YCharSize);
xf86ErrorFVerb(DEBUG_VERB,
" NumberOfPlanes: %d\n", mode->NumberOfPlanes);
xf86ErrorFVerb(DEBUG_VERB,
" BitsPerPixel: %d\n", mode->BitsPerPixel);
xf86ErrorFVerb(DEBUG_VERB,
" NumberOfBanks: %d\n", mode->NumberOfBanks);
xf86ErrorFVerb(DEBUG_VERB,
" MemoryModel: %d\n", mode->MemoryModel);
xf86ErrorFVerb(DEBUG_VERB,
" BankSize: %d\n", mode->BankSize);
xf86ErrorFVerb(DEBUG_VERB,
" NumberOfImages: %d\n", mode->NumberOfImages);
xf86ErrorFVerb(DEBUG_VERB,
" RedMaskSize: %d\n", mode->RedMaskSize);
xf86ErrorFVerb(DEBUG_VERB,
" RedFieldPosition: %d\n", mode->RedFieldPosition);
xf86ErrorFVerb(DEBUG_VERB,
" GreenMaskSize: %d\n", mode->GreenMaskSize);
xf86ErrorFVerb(DEBUG_VERB,
" GreenFieldPosition: %d\n", mode->GreenFieldPosition);
xf86ErrorFVerb(DEBUG_VERB,
" BlueMaskSize: %d\n", mode->BlueMaskSize);
xf86ErrorFVerb(DEBUG_VERB,
" BlueFieldPosition: %d\n", mode->BlueFieldPosition);
xf86ErrorFVerb(DEBUG_VERB,
" RsvdMaskSize: %d\n", mode->RsvdMaskSize);
xf86ErrorFVerb(DEBUG_VERB,
" RsvdFieldPosition: %d\n", mode->RsvdFieldPosition);
xf86ErrorFVerb(DEBUG_VERB,
" DirectColorModeInfo: %d\n", mode->DirectColorModeInfo);
if (major >= 2) {
xf86ErrorFVerb(DEBUG_VERB,
" PhysBasePtr: 0x%lx\n",
(unsigned long)mode->PhysBasePtr);
if (major >= 3) {
xf86ErrorFVerb(DEBUG_VERB,
" LinBytesPerScanLine: %d\n", mode->LinBytesPerScanLine);
xf86ErrorFVerb(DEBUG_VERB,
" BnkNumberOfImagePages: %d\n", mode->BnkNumberOfImagePages);
xf86ErrorFVerb(DEBUG_VERB,
" LinNumberOfImagePages: %d\n", mode->LinNumberOfImagePages);
xf86ErrorFVerb(DEBUG_VERB,
" LinRedMaskSize: %d\n", mode->LinRedMaskSize);
xf86ErrorFVerb(DEBUG_VERB,
" LinRedFieldPosition: %d\n", mode->LinRedFieldPosition);
xf86ErrorFVerb(DEBUG_VERB,
" LinGreenMaskSize: %d\n", mode->LinGreenMaskSize);
xf86ErrorFVerb(DEBUG_VERB,
" LinGreenFieldPosition: %d\n", mode->LinGreenFieldPosition);
xf86ErrorFVerb(DEBUG_VERB,
" LinBlueMaskSize: %d\n", mode->LinBlueMaskSize);
xf86ErrorFVerb(DEBUG_VERB,
" LinBlueFieldPosition: %d\n", mode->LinBlueFieldPosition);
xf86ErrorFVerb(DEBUG_VERB,
" LinRsvdMaskSize: %d\n", mode->LinRsvdMaskSize);
xf86ErrorFVerb(DEBUG_VERB,
" LinRsvdFieldPosition: %d\n", mode->LinRsvdFieldPosition);
xf86ErrorFVerb(DEBUG_VERB,
" MaxPixelClock: %ld\n", (unsigned long)mode->MaxPixelClock);
}
}
if (!modeOK) {
VBEFreeModeInfo(mode);
return NULL;
}
pMode = xnfcalloc(sizeof(DisplayModeRec), 1);
pMode->status = MODE_OK;
pMode->type = M_T_BUILTIN;
pMode->HDisplay = mode->XResolution;
pMode->VDisplay = mode->YResolution;
data = xnfcalloc(sizeof(VbeModeInfoData), 1);
data->mode = id;
data->data = mode;
pMode->PrivSize = sizeof(VbeModeInfoData);
pMode->Private = (INT32*)data;
pMode->next = NULL;
return pMode;
}
DisplayModePtr
VBEGetModePool(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock *vbe,
int modeTypes)
{
DisplayModePtr pMode, p = NULL, modePool = NULL;
int i = 0;
if (modeTypes & V_MODETYPE_VBE) {
while (vbe->VideoModePtr[i] != 0xffff) {
int id = vbe->VideoModePtr[i++];
if ((pMode = CheckMode(pScrn, pVbe, vbe, id, modeTypes)) != NULL) {
ModeStatus status = MODE_OK;
if (pScrn->display->virtualX > 0 &&
pMode->HDisplay > pScrn->display->virtualX) {
status = MODE_VIRTUAL_X;
}
if (pScrn->display->virtualY > 0 &&
pMode->VDisplay > pScrn->display->virtualY) {
status = MODE_VIRTUAL_Y;
}
if (status != MODE_OK) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Not using mode \"%dx%d\" (%s)\n",
pMode->HDisplay, pMode->VDisplay,
xf86ModeStatusToString(status));
} else {
if (p == NULL) {
modePool = pMode;
} else {
p->next = pMode;
}
pMode->prev = NULL;
p = pMode;
}
}
}
}
if (modeTypes & V_MODETYPE_VGA) {
for (i = 0; i < 0x7F; i++) {
if ((pMode = CheckMode(pScrn, pVbe, vbe, i, modeTypes)) != NULL) {
ModeStatus status = MODE_OK;
if (pScrn->display->virtualX > 0 &&
pMode->HDisplay > pScrn->display->virtualX) {
status = MODE_VIRTUAL_X;
}
if (pScrn->display->virtualY > 0 &&
pMode->VDisplay > pScrn->display->virtualY) {
status = MODE_VIRTUAL_Y;
}
if (status != MODE_OK) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Not using mode \"%dx%d\" (%s)\n",
pMode->HDisplay, pMode->VDisplay,
xf86ModeStatusToString(status));
} else {
if (p == NULL) {
modePool = pMode;
} else {
p->next = pMode;
}
pMode->prev = NULL;
p = pMode;
}
}
}
}
return modePool;
}
void
VBESetModeNames(DisplayModePtr pMode)
{
if (!pMode)
return;
do {
if (!pMode->name) {
if (pMode->HDisplay > 10000 || pMode->HDisplay < 0 ||
pMode->VDisplay > 10000 || pMode->VDisplay < 0) {
pMode->name = strdup("BADMODE");
} else {
pMode->name = xnfalloc(4 + 1 + 4 + 1);
sprintf(pMode->name, "%dx%d", pMode->HDisplay, pMode->VDisplay);
}
}
pMode = pMode->next;
} while (pMode);
}
void
VBESetModeParameters(ScrnInfoPtr pScrn, vbeInfoPtr pVbe)
{
DisplayModePtr pMode;
VbeModeInfoData *data;
pMode = pScrn->modes;
do {
DisplayModePtr p, best = NULL;
ModeStatus status;
for (p = pScrn->monitor->Modes; p != NULL; p = p->next) {
if ((p->HDisplay != pMode->HDisplay) ||
(p->VDisplay != pMode->VDisplay) ||
(p->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2)))
continue;
status = xf86CheckModeForMonitor(p, pScrn->monitor);
if (status != MODE_OK)
continue;
if (!best || (p->Clock > best->Clock))
best = p;
}
if (best) {
int clock;
data = (VbeModeInfoData*)pMode->Private;
pMode->HSync = (float)best->Clock * 1000.0 / best->HTotal + 0.5;
pMode->VRefresh = pMode->HSync / best->VTotal + 0.5;
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Attempting to use %dHz refresh for mode \"%s\" (%x)\n",
(int)pMode->VRefresh, pMode->name, data->mode);
data->block = xcalloc(sizeof(VbeCRTCInfoBlock), 1);
data->block->HorizontalTotal = best->HTotal;
data->block->HorizontalSyncStart = best->HSyncStart;
data->block->HorizontalSyncEnd = best->HSyncEnd;
data->block->VerticalTotal = best->VTotal;
data->block->VerticalSyncStart = best->VSyncStart;
data->block->VerticalSyncEnd = best->VSyncEnd;
data->block->Flags = ((best->Flags & V_NHSYNC) ? CRTC_NHSYNC : 0) |
((best->Flags & V_NVSYNC) ? CRTC_NVSYNC : 0);
data->block->PixelClock = best->Clock * 1000;
clock = VBEGetPixelClock(pVbe, data->mode, data->block->PixelClock);
#ifdef DEBUG
ErrorF("Setting clock %.2fMHz, closest is %.2fMHz\n",
(double)data->block->PixelClock / 1000000.0,
(double)clock / 1000000.0);
#endif
if (clock)
data->block->PixelClock = clock;
data->mode |= (1 << 11);
data->block->RefreshRate = ((double)(data->block->PixelClock) /
(double)(best->HTotal * best->VTotal)) * 100;
}
pMode = pMode->next;
} while (pMode != pScrn->modes);
}
int
VBEValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes,
char **modeNames, ClockRangePtr clockRanges,
int *linePitches, int minPitch, int maxPitch, int pitchInc,
int minHeight, int maxHeight, int virtualX, int virtualY,
int apertureSize, LookupModeFlags strategy)
{
return xf86ValidateModes(scrp, availModes, modeNames, clockRanges,
linePitches, minPitch, maxPitch, pitchInc,
minHeight, maxHeight, virtualX, virtualY,
apertureSize, strategy);
}
void
VBEPrintModes(ScrnInfoPtr scrp)
{
xf86PrintModes(scrp);
}