Skip to content

Instantly share code, notes, and snippets.

@knazarov
Created March 9, 2021 15:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save knazarov/40348fe805fce1fdaada11c863380109 to your computer and use it in GitHub Desktop.
Save knazarov/40348fe805fce1fdaada11c863380109 to your computer and use it in GitHub Desktop.
Qemu patch to allow generating EDID information for 5k resolution
diff --git a/hw/display/edid-generate.c b/hw/display/edid-generate.c
index b0ce583d436..9941fd59aab 100644
--- a/hw/display/edid-generate.c
+++ b/hw/display/edid-generate.c
@@ -129,17 +129,17 @@ static void edid_fill_modes(uint8_t *edid, uint8_t *xtra3, uint8_t *dta,
}
}
-static void edid_checksum(uint8_t *edid)
+static void edid_checksum(uint8_t *edid, size_t len)
{
uint32_t sum = 0;
int i;
- for (i = 0; i < 127; i++) {
+ for (i = 0; i < len; i++) {
sum += edid[i];
}
sum &= 0xff;
if (sum) {
- edid[127] = 0x100 - sum;
+ edid[len] = 0x100 - sum;
}
}
@@ -296,12 +296,60 @@ uint32_t qemu_edid_dpi_to_mm(uint32_t dpi, uint32_t res)
return res * 254 / 10 / dpi;
}
+static void qemu_displayid_generate(uint8_t* did, uint32_t refresh_rate,
+ uint32_t xres, uint32_t yres,
+ uint32_t xmm, uint32_t ymm)
+{
+ /* pull some realistic looking timings out of thin air */
+ uint32_t xfront = xres * 25 / 100;
+ uint32_t xsync = xres * 3 / 100;
+ uint32_t xblank = xres * 35 / 100;
+
+ uint32_t yfront = yres * 5 / 1000;
+ uint32_t ysync = yres * 5 / 1000;
+ uint32_t yblank = yres * 35 / 1000;
+
+ uint64_t clock = ((uint64_t)refresh_rate * (xres + xblank) * (yres + yblank)) / 10000000;
+
+ did[0] = 0x70; // display id extension
+ did[1] = 0x13; // version 1.3
+ did[2] = 23; // length
+ did[3] = 0x03; // product type (0x03 == standalone display device)
+
+ uint32_t offset = 5;
+
+ did[offset] = 0x03; //Detailed Timings Data Block
+ did[offset+1] = 0x00; // revision
+ did[offset+2] = 0x14; // block length
+
+ uint32_t block = offset + 3;
+
+ did[block] = clock & 0xff;
+ did[block+1] = (clock & 0xff00) >> 8;
+ did[block+2] = (clock & 0xff0000) >> 16;
+
+ did[block+3] = 0x88;
+
+ stw_le_p(did + block+4, 0xffff & (xres-1));
+ stw_le_p(did + block+6, 0xffff & (xblank-1));
+ stw_le_p(did + block+8, 0xffff & (xfront-1));
+ stw_le_p(did + block+10, 0xffff & (xsync-1));
+
+ stw_le_p(did + block+12, 0xffff & (yres-1));
+ stw_le_p(did + block+14, 0xffff & (yblank-1));
+ stw_le_p(did + block+16, 0xffff & (yfront-1));
+ stw_le_p(did + block+18, 0xffff & (ysync-1));
+
+ edid_checksum(did + 1, did[2] + 4);
+}
+
void qemu_edid_generate(uint8_t *edid, size_t size,
qemu_edid_info *info)
{
uint32_t desc = 54;
uint8_t *xtra3 = NULL;
uint8_t *dta = NULL;
+ uint8_t *did = NULL;
uint32_t width_mm, height_mm;
uint32_t refresh_rate = info->refresh_rate ? info->refresh_rate : 75000;
uint32_t dpi = 100; /* if no width_mm/height_mm */
@@ -429,13 +477,28 @@ void qemu_edid_generate(uint8_t *edid, size_t size,
desc += 18;
}
+ /* =============== dislpay id extensions =============== */
+
+ if (size >= 384) {
+ did = edid + 256;
+ edid[126]++;
+
+ qemu_displayid_generate(did, refresh_rate, info->prefx, info->prefy,
+ width_mm, height_mm);
+ }
+
+
/* =============== finish up =============== */
edid_fill_modes(edid, xtra3, dta, info->maxx, info->maxy);
- edid_checksum(edid);
+ edid_checksum(edid, 127);
if (dta) {
- edid_checksum(dta);
+ edid_checksum(dta, 127);
+ }
+ if (did) {
+ edid_checksum(did, 127);
}
+
}
size_t qemu_edid_size(uint8_t *edid)
diff --git a/hw/display/vga-pci.c b/hw/display/vga-pci.c
index 48d29630ab7..62fb5c38c1f 100644
--- a/hw/display/vga-pci.c
+++ b/hw/display/vga-pci.c
@@ -49,7 +49,7 @@ struct PCIVGAState {
qemu_edid_info edid_info;
MemoryRegion mmio;
MemoryRegion mrs[4];
- uint8_t edid[256];
+ uint8_t edid[384];
};
#define TYPE_PCI_VGA "pci-vga"
diff --git a/qemu-edid.c b/qemu-edid.c
index 1cd6a951723..028f2d181a1 100644
--- a/qemu-edid.c
+++ b/qemu-edid.c
@@ -41,7 +41,7 @@ static void usage(FILE *out)
int main(int argc, char *argv[])
{
FILE *outfile = NULL;
- uint8_t blob[256];
+ uint8_t blob[384];
uint32_t dpi = 100;
int rc;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment