diff options
Diffstat (limited to 'QemuVGADriver/src')
-rw-r--r-- | QemuVGADriver/src/QemuEdid.c | 1 | ||||
-rw-r--r-- | QemuVGADriver/src/QemuVga.c | 42 | ||||
-rw-r--r-- | QemuVGADriver/src/QemuVga.h | 18 |
3 files changed, 42 insertions, 19 deletions
diff --git a/QemuVGADriver/src/QemuEdid.c b/QemuVGADriver/src/QemuEdid.c new file mode 100644 index 0000000..57de244 --- /dev/null +++ b/QemuVGADriver/src/QemuEdid.c @@ -0,0 +1 @@ +#include <Video.h>
#include "VideoDriverPrivate.h"
#include "logger.h"
#include "QemuVga.h"
/* List of video modes */
struct vMode *vModes;
/* Default modes if no EDID (must be 0 terminated) */
static struct _vMode defaultVModes[] = {
{ 640, 480 },
{ 800, 600 },
{ 1024, 768 },
{ 1280, 1024 },
{ 1600, 1200 },
{ 1920, 1080 },
{ 1920, 1200 },
};
/* EDID standard timings */
static struct _vMode edidStdVModes[] = {
{ 800, 600 }, /* 800x600 @ 60Hz */
{ 800, 600 }, /* 800x600 @ 56Hz */
{ 640, 480 }, /* 640x480 @ 75Hz */
{ 640, 480 }, /* 640x480 @ 72Hz */
{ 640, 480 }, /* 640x480 @ 67Hz */
{ 640, 480 }, /* 640x480 @ 60Hz */
{ 720, 400 }, /* 720x400 @ 88Hz */
{ 720, 400 }, /* 720x400 @ 70Hz */
{ 1280, 1024 }, /* 1280x1024 @ 75Hz */
{ 1024, 768 }, /* 1024x768 @ 75Hz */
{ 1024, 768 }, /* 1024x768 @ 72Hz */
{ 1024, 768 }, /* 1024x768 @ 60Hz */
{ 1024, 768 }, /* 1024x768 @ 87Hz */
{ 832, 624 }, /* 832x624 @ 75Hz */
{ 800, 600 }, /* 800x600 @ 75Hz */
{ 800, 600 }, /* 800x600 @ 72Hz */
{ 0, 0 }, /* Reserved */
{ 0, 0 }, /* Reserved */
{ 0, 0 }, /* Reserved */
{ 0, 0 }, /* Reserved */
{ 0, 0 }, /* Reserved */
{ 0, 0 }, /* Reserved */
{ 0, 0 }, /* Reserved */
{ 1152, 870 }, /* 1152x870 @ 75Hz */
};
/* EDID extended standard timings */
static struct _vMode edidExtStdVModes[] = {
{ 1152, 864 }, /* 1152x864 @ 85Hz */
{ 1024, 768 }, /* 1024x768 @ 75Hz */
{ 800, 600 }, /* 800x600 @ 85Hz */
{ 848, 480 }, /* 848x480 @ 60Hz */
{ 640, 480 }, /* 640x480 @ 85Hz */
{ 720, 400 }, /* 720x400 @ 85Hz */
{ 640, 400 }, /* 640x400 @ 85Hz */
{ 640, 350 }, /* 640x350 @ 85Hz */
{ 1280, 1024 }, /* 1280x1024 @ 85Hz */
{ 1280, 1024 }, /* 1280x1024 @ 60Hz */
{ 1280, 960 }, /* 1280x960 @ 85Hz */
{ 1280, 960 }, /* 1280x960 @ 60Hz */
{ 1280, 768 }, /* 1280x768 @ 85Hz */
{ 1280, 768 }, /* 1280x768 @ 75Hz */
{ 1280, 768 }, /* 1280x768 @ 60Hz */
{ 1280, 768 }, /* 1280x768 @ 60Hz (CVT-RB) */
{ 1440, 1050 }, /* 1440x1050 @ 75Hz */
{ 1440, 1050 }, /* 1440x1050 @ 60Hz */
{ 1440, 1050 }, /* 1440x1050 @ 60Hz (CVT-RB) */
{ 1440, 900 }, /* 1440x900 @ 85Hz */
{ 1440, 900 }, /* 1440x900 @ 75Hz */
{ 1440, 900 }, /* 1440x900 @ 60Hz (CVT-RB) */
{ 1360, 768 }, /* 1360x768 @ 60Hz */
{ 1360, 768 }, /* 1360x768 @ 60Hz (CVT-RB) */
{ 1600, 1200 }, /* 1600x1200 @ 70Hz */
{ 1600, 1200 }, /* 1600x1200 @ 65Hz */
{ 1600, 1200 }, /* 1600x1200 @ 60Hz */
{ 1680, 1050 }, /* 1680x1050 @ 85Hz */
{ 1680, 1050 }, /* 1680x1050 @ 75Hz */
{ 1680, 1050 }, /* 1680x1050 @ 60Hz */
{ 1680, 1050 }, /* 1680x1050 @ 60Hz (CVT-RB) */
{ 1440, 1050 }, /* 1440x1050 @ 85Hz */
{ 1920, 1200 }, /* 1920x1200 @ 60Hz */
{ 1920, 1200 }, /* 1920x1200 @ 60Hz (CVT-RB) */
{ 1856, 1392 }, /* 1856x1392 @ 75Hz */
{ 1856, 1392 }, /* 1856x1392 @ 60Hz */
{ 1792, 1344 }, /* 1792x1344 @ 75Hz */
{ 1792, 1344 }, /* 1792x1344 @ 60Hz */
{ 1600, 1200 }, /* 1600x1200 @ 85Hz */
{ 1600, 1200 }, /* 1600x1200 @ 75Hz */
{ 0, 0 }, /* Reserved */
{ 0, 0 }, /* Reserved */
{ 0, 0 }, /* Reserved */
{ 0, 0 }, /* Reserved */
{ 1920, 1440 }, /* 1920x1440 @ 75Hz */
{ 1920, 1440 }, /* 1920x1440 @ 60Hz */
{ 1920, 1200 }, /* 1920x1200 @ 75Hz */
{ 1920, 1200 }, /* 1920x1200 @ 60Hz */
};
/* EDID timing extension modes */
static struct _vMode edidTimingExtensionVModes[] = {
{ 640, 480 }, /* DMT0659 */
{ 720, 480 }, /* 480p */
{ 720, 480 }, /* 480pH */
{ 1280, 720 }, /* 720p */
{ 1920, 540 }, /* 1080i */
{ 1440, 240 }, /* 480i */
{ 1440, 240 }, /* 480iH */
{ 1440, 240 }, /* 240p */
{ 1440, 240 }, /* 240pH */
{ 2880, 240 }, /* 480i4x */
{ 2880, 240 }, /* 480i4xH */
{ 2880, 240 }, /* 240p4x */
{ 2880, 240 }, /* 240p4xH */
{ 1440, 480 }, /* 480p2x */
{ 1440, 480 }, /* 480p2xH */
{ 1920, 1080 }, /* 1080p */
{ 720, 576 }, /* 576p */
{ 720, 576 }, /* 576pH */
{ 1280, 720 }, /* 720p50 */
{ 1920, 540 }, /* 1080i25 */
{ 1440, 288 }, /* 576i */
{ 1440, 288 }, /* 576iH */
{ 1440, 288 }, /* 288p */
{ 1440, 288 }, /* 288pH */
{ 2880, 288 }, /* 576i4x */
{ 2880, 288 }, /* 576i4xH */
{ 2880, 288 }, /* 288p4x */
{ 2880, 288 }, /* 288p4xH */
{ 1440, 576 }, /* 576p2x */
{ 1440, 576 }, /* 576p2xH */
{ 1920, 1080 }, /* 1080p50 */
{ 1920, 1080 }, /* 1080p24 */
{ 1920, 1080 }, /* 1080p25 */
{ 1920, 1080 }, /* 1080p30 */
{ 2880, 240 }, /* 480p4x */
{ 2880, 240 }, /* 480p4xH */
{ 2880, 576 }, /* 576p4x */
{ 2880, 576 }, /* 576p4xH */
{ 1920, 540 }, /* 1080i25 */
{ 1920, 540 }, /* 1080i50 */
{ 1280, 720 }, /* 720p100 */
{ 720, 576 }, /* 576p100 */
{ 720, 576 }, /* 576p100H */
{ 1440, 576 }, /* 576i50 */
{ 1440, 576 }, /* 576i50H */
{ 1920, 540 }, /* 1080i60 */
{ 1280, 720 }, /* 720p120 */
{ 720, 576 }, /* 480p119 */
{ 720, 576 }, /* 480p119H */
{ 1440, 576 }, /* 480i59 */
{ 1440, 576 }, /* 480i59H */
{ 720, 576 }, /* 576p200 */
{ 720, 576 }, /* 576p200H */
{ 1440, 288 }, /* 576i100 */
{ 1440, 288 }, /* 576i100H */
{ 720, 480 }, /* 480p239 */
{ 720, 480 }, /* 480p239H */
{ 1440, 240 }, /* 480i119 */
{ 1440, 240 }, /* 480i119H */
{ 1280, 720 }, /* 720p24 */
{ 1280, 720 }, /* 720p25 */
{ 1280, 720 }, /* 720p30 */
{ 1920, 1080 }, /* 1080p120 */
{ 1920, 1080 }, /* 1080p100 */
{ 1280, 720 }, /* 720p24 */
{ 1280, 720 }, /* 720p25 */
{ 1280, 720 }, /* 720p30 */
{ 1280, 720 }, /* 720p50 */
{ 1650, 750 }, /* 720p */
{ 1280, 720 }, /* 720p100 */
{ 1280, 720 }, /* 720p120 */
{ 1920, 1080 }, /* 1080p24 */
{ 1920, 1280 }, /* 1080p25 */
{ 1920, 1280 }, /* 1080p30 */
{ 1920, 1280 }, /* 1080p50 */
{ 1920, 1280 }, /* 1080p */
{ 1920, 1280 }, /* 1080p100 */
{ 1920, 1280 }, /* 1080p120 */
{ 1680, 720 }, /* 720p2x24 */
{ 1680, 720 }, /* 720p2x25 */
{ 1680, 720 }, /* 720p2x30 */
{ 1680, 720 }, /* 720p2x50 */
{ 1680, 720 }, /* 720p2x */
{ 1680, 720 }, /* 720p2x100 */
{ 1680, 720 }, /* 720p2x120 */
{ 2560, 1080 }, /* 1080p2x24 */
{ 2560, 1080 }, /* 1080p2x25 */
{ 2560, 1080 }, /* 1080p2x30 */
{ 2560, 1080 }, /* 1080p2x50 */
{ 2560, 1080 }, /* 1080p2x */
{ 2560, 1080 }, /* 1080p2x100 */
{ 2560, 1080 }, /* 1080p2x120 */
{ 3840, 2160 }, /* 2160p24 */
{ 3840, 2160 }, /* 2160p25 */
{ 3840, 2160 }, /* 2160p30 */
{ 3840, 2160 }, /* 2160p50 */
{ 3840, 2160 }, /* 2160p */
{ 4096, 2160 }, /* 2160p24 */
{ 4096, 2160 }, /* 2160p25 */
{ 4096, 2160 }, /* 2160p30 */
{ 4096, 2160 }, /* 2160p50 */
{ 4096, 2160 }, /* 2160p */
{ 3840, 2160 }, /* 2160p24 */
{ 3840, 2160 }, /* 2160p25 */
{ 3840, 2160 }, /* 2160p30 */
{ 3840, 2160 }, /* 2160p50 */
{ 3840, 2160 }, /* 2160p */
{ 1280, 720 }, /* 720p48 */
{ 1280, 720 }, /* 720p48 */
{ 1680, 720 }, /* 720p2x48 */
{ 1920, 1280 }, /* 1080p48 */
{ 1920, 1280 }, /* 1080p48 */
{ 2560, 1080 }, /* 1080p2x48 */
{ 3840, 2160 }, /* 2160p48 */
{ 4096, 2160 }, /* 2160p48 */
{ 3840, 2160 }, /* 2160p48 */
{ 3840, 2160 }, /* 2160p100 */
{ 3840, 2160 }, /* 2160p120 */
{ 3840, 2160 }, /* 2160p100 */
{ 3840, 2160 }, /* 2160p120 */
{ 5120, 2160 }, /* 2160p2x24 */
{ 5120, 2160 }, /* 2160p2x25 */
{ 5120, 2160 }, /* 2160p2x30 */
{ 5120, 2160 }, /* 2160p2x48 */
{ 5120, 2160 }, /* 2160p2x50 */
{ 5120, 2160 }, /* 2160p2x */
{ 5120, 2160 }, /* 2160p2x100 */
{ 0, 0 }, /* Reserved */
};
struct _vMode *getVMode(UInt16 idx)
{
struct vMode *v = vModes;
UInt16 i = 0;
while (v != NULL) {
if (i == idx) {
return v->mode;
}
v = v->next;
i++;
}
return NULL;
}
static void dumpVModeList(void)
{
struct vMode *v = vModes;
while (v != NULL) {
lprintf(" %d, %d\n", v->mode->width, v->mode->height);
v = v->next;
}
}
static UInt16 getVModeListSize(void)
{
struct vMode *v = vModes;
UInt16 i = 0;
while (v != NULL) {
v = v->next;
i++;
}
return i;
}
static void addVModeToList(struct _vMode *vMode)
{
/* Add mode to list */
struct vMode **v = &vModes;
struct vMode *n;
while (*v != NULL) {
/* Don't add mode if resulting framebuffer is too
large for PCI MMIO space */
if (vMode->width * vMode->height * 4 > GLOBAL.boardFBMappedSize) {
return;
}
/* Don't add duplicate mode if it already exists */
if ((*v)->mode->width == vMode->width &&
(*v)->mode->height == vMode->height) {
return;
}
/* Add mode in order */
if (((*v)->mode->width == vMode->width &&
(*v)->mode->height > vMode->height) ||
((*v)->mode->width > vMode->width)) {
n = PoolAllocateResident(sizeof(struct vMode), true);
n->next = *v;
n->mode = vMode;
*v = n;
return;
}
v = &(*v)->next;
}
n = PoolAllocateResident(sizeof(struct vMode), true);
n->next = NULL;
n->mode = vMode;
*v = n;
}
static UInt8 EdidReadB(UInt16 port)
{
UInt8 *ptr, val;
ptr = (UInt8 *)((UInt32)GLOBAL.boardRegAddress + port);
val = *ptr;
SynchronizeIO();
return val;
}
static UInt16 GetEdidSize()
{
return 0x80 * ((UInt16)EdidReadB(0x7e) + 1);
}
static void ParseEdid(UInt8 *edid)
{
int i, j, d, idx;
/* Standard modes */
lprintf("Standard modes: \n");
for (i = 35; i <= 37; i++) {
for (j = 0; j <= 7; j++) {
if (edid[i] & (1 << j)) {
idx = ((i - 35) << 3) + j;
lprintf(" %d, %d\n", edidStdVModes[idx].width,
edidStdVModes[idx].height);
addVModeToList(&edidStdVModes[idx]);
}
}
}
/* Extended standard modes */
lprintf("Extended standard modes: \n");
d = i = 54;
while (d < 126) {
/* Search for descriptor */
if (edid[d] == 0x0 && edid[d + 1] == 0x0 && edid[d + 2] == 0x0 &&
edid[d + 3] == 0xf7 && edid[d + 4] == 0x0) {
for (i = d + 6; i <= d + 11; i++) {
for (j = 0; j <= 7; j++) {
if (edid[i] & (1 << j)) {
idx = ((i - d - 6) << 3) + j;
lprintf(" %d, %d\n", edidExtStdVModes[idx].width,
edidExtStdVModes[idx].height);
addVModeToList(&edidExtStdVModes[idx]);
}
}
}
break;
}
d += 18;
}
/* Extension block modes */
lprintf("Extension block modes: \n");
if (edid[126] > 0) {
/* Search for descriptor */
i = 128;
if (edid[i] == 0x2 && edid[i + 1] == 0x3) {
/* Data present: check for video block */
d = edid[i + 2];
if (d > 0x4 && (edid[i + 4] & 0xf0) == (2 << 5)) {
for (j = 0; j < (edid[i + 4] & 0x1f); j++) {
idx = edid[(i + 5 + j)];
lprintf(" %d, %d\n", edidTimingExtensionVModes[idx].width,
edidTimingExtensionVModes[idx].height);
addVModeToList(&edidTimingExtensionVModes[idx]);
}
}
}
}
}
static void ParseDefaultVModes() {
UInt8 defaultVModeCount;
int i;
defaultVModeCount = sizeof(defaultVModes) / sizeof(struct _vMode);
lprintf("Default modes:\n");
for (i = 0; i < defaultVModeCount; i++) {
lprintf(" %d, %d\n", defaultVModes[i].width, defaultVModes[i].height);
addVModeToList(&defaultVModes[i]);
}
}
UInt16 QemuVga_ReadEdidModes(void)
{
UInt16 edidSize = GetEdidSize();
UInt8 *edid;
int i;
if (EdidReadB(0x0) != 0x0 || EdidReadB(0x1) != 0xff) {
lprintf("No valid EDID detected, using default modes\n");
ParseDefaultVModes();
return getVModeListSize();
}
lprintf("EDID size: %d bytes, reading modes from EDID...\n", edidSize);
edid = (UInt8 *)PoolAllocateResident(edidSize, true);
if (!edid)
return;
for (i = 0; i < edidSize; i++) {
edid[i] = EdidReadB(i);
}
ParseEdid(edid);
PoolDeallocate(edid);
lprintf("Final mode list:\n");
dumpVModeList();
return getVModeListSize();
}
\ No newline at end of file diff --git a/QemuVGADriver/src/QemuVga.c b/QemuVGADriver/src/QemuVga.c index 4584242..7b6dd23 100644 --- a/QemuVGADriver/src/QemuVga.c +++ b/QemuVGADriver/src/QemuVga.c @@ -4,13 +4,8 @@ #include "QemuVga.h" #include <Timer.h> -/* List of supported modes */ -struct vMode { - UInt32 width; - UInt32 height; -}; - -static struct vMode vModes[] = { +/* +static struct _vMode defaultVModes[] = { { 640, 480 }, { 800, 600 }, { 1024, 768 }, @@ -18,9 +13,9 @@ static struct vMode vModes[] = { { 1600, 1200 }, { 1920, 1080 }, { 1920, 1200 }, - { 0,0 } + { 0, 0 } }; - +*/ static void VgaWriteB(UInt16 port, UInt8 val) { UInt8 *ptr; @@ -152,6 +147,8 @@ OSStatus QemuVga_Init(void) { UInt16 id, i; UInt32 mem, width, height, depth; + Boolean modeFound = false; + struct vMode *v; lprintf("First MMIO read...\n"); id = DispiReadW(VBE_DISPI_INDEX_ID); @@ -174,16 +171,23 @@ OSStatus QemuVga_Init(void) lprintf("Current setting: %dx%dx%d\n", width, height, depth); GLOBAL.depth = GLOBAL.bootDepth = depth; - for (i = 0; vModes[i].width; i++) { - if (width == vModes[i].width && height == vModes[i].height) + GLOBAL.numModes = QemuVga_ReadEdidModes(); + lprintf("Number of modes: %d\n", GLOBAL.numModes); + + for (i = 0, v = vModes; v != NULL; v = v->next, i++) { + if (width == v->mode->width && height == v->mode->height) { + modeFound = true; break; + } } - if (!vModes[i].width) { + + if (!modeFound) { lprintf("Not found in list ! using default.\n"); i = 0; + } else { + lprintf("Using mode: %d\n", i); } GLOBAL.bootMode = i; - GLOBAL.numModes = sizeof(vModes) / sizeof(struct vMode) - 1; QemuVga_SetMode(GLOBAL.bootMode, depth, 0); @@ -305,9 +309,9 @@ OSStatus QemuVga_GetModeInfo(UInt32 index, UInt32 *width, UInt32 *height) if (index >= GLOBAL.numModes) return paramErr; if (width) - *width = vModes[index].width; + *width = getVMode(index)->width; if (height) - *height = vModes[index].height; + *height = getVMode(index)->height; return noErr; } @@ -318,8 +322,8 @@ OSStatus QemuVga_GetModePages(UInt32 index, UInt32 depth, if (index >= GLOBAL.numModes) return paramErr; - width = vModes[index].width; - height = vModes[index].height; + width = getVMode(index)->width; + height = getVMode(index)->height; pBytes = width * ((depth + 7) / 8) * height; if (pageSize) *pageSize = pBytes; @@ -340,8 +344,8 @@ OSStatus QemuVga_SetMode(UInt32 mode, UInt32 depth, UInt32 page) if (mode >= GLOBAL.numModes) return paramErr; - width = vModes[mode].width; - height = vModes[mode].height; + width = getVMode(mode)->width; + height = getVMode(mode)->height; QemuVga_GetModePages(mode, depth, &pageSize, &numPages); lprintf("Set Mode: %dx%dx%d has %d pages\n", width, height, depth, numPages); if (page >= numPages) diff --git a/QemuVGADriver/src/QemuVga.h b/QemuVGADriver/src/QemuVga.h index 69e80fa..f070bb7 100644 --- a/QemuVGADriver/src/QemuVga.h +++ b/QemuVGADriver/src/QemuVga.h @@ -45,6 +45,22 @@ #define VBE_DISPI_LFB_ENABLED 0x40 #define VBE_DISPI_NOCLEARMEM 0x80 +/* --- VModes */ + +struct _vMode { + UInt32 width; + UInt32 height; +}; + +struct vMode { + struct vMode *next; + struct _vMode *mode; +}; + +extern struct vMode *vModes; +extern struct _vMode defaultVModes[]; +extern struct _vMode *getVMode(UInt16 idx); + /* --- Internal APIs */ extern OSStatus QemuVga_Init(); @@ -56,6 +72,8 @@ extern OSStatus QemuVga_Close(); extern void QemuVga_EnableInterrupts(void); extern void QemuVga_DisableInterrupts(void); +extern UInt16 QemuVga_ReadEdidModes(void); + extern OSStatus QemuVga_SetDepth(UInt32 bpp); extern OSStatus QemuVga_SetColorEntry(UInt32 index, RGBColor *color); |