From 72d277a70e8b2d4eb1b3667ab934fb1fecf41410 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 25 Sep 2018 09:56:42 +0200 Subject: display/edid: add edid generator to qemu. EDID is a metadata format to describe monitors. On physical hardware the monitor has an eeprom with that data block which can be read over i2c bus. On a linux system you can usually find the EDID data block in /sys/class/drm/$card/$connector/edid. xorg ships a edid-decode utility which you can use to turn the blob into readable form. I think it would be a good idea to use EDID for virtual displays too. Needs changes in both qemu and guest kms drivers. This patch is the first step, it adds an generator for EDID blobs to qemu. Comes with a qemu-edid test tool included. With EDID we can pass more information to the guest. Names and serial numbers, so the guests display configuration has no boring "Unknown Monitor". List of video modes. Display resolution, pretty important in case we want add HiDPI support some day. Signed-off-by: Gerd Hoffmann Message-id: 20180925075646.25114-2-kraxel@redhat.com --- include/hw/display/edid.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 include/hw/display/edid.h (limited to 'include') diff --git a/include/hw/display/edid.h b/include/hw/display/edid.h new file mode 100644 index 0000000000..63b60015c3 --- /dev/null +++ b/include/hw/display/edid.h @@ -0,0 +1,18 @@ +#ifndef EDID_H +#define EDID_H + +typedef struct qemu_edid_info { + const char *vendor; + const char *name; + const char *serial; + uint32_t dpi; + uint32_t prefx; + uint32_t prefy; + uint32_t maxx; + uint32_t maxy; +} qemu_edid_info; + +void qemu_edid_generate(uint8_t *edid, size_t size, + qemu_edid_info *info); + +#endif /* EDID_H */ -- cgit 1.4.1 From e7992fc5a002003ae865685ad4635b952c1ca9bf Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 25 Sep 2018 09:56:43 +0200 Subject: display/edid: add qemu_edid_size() Helper function to figure the size of a edid blob, by checking how many extensions are present. Both the base edid blob and the extensions are 128 bytes in size. Signed-off-by: Gerd Hoffmann Message-id: 20180925075646.25114-3-kraxel@redhat.com --- hw/display/edid-generate.c | 14 ++++++++++++++ include/hw/display/edid.h | 1 + 2 files changed, 15 insertions(+) (limited to 'include') diff --git a/hw/display/edid-generate.c b/hw/display/edid-generate.c index b3e493da19..c80397ea96 100644 --- a/hw/display/edid-generate.c +++ b/hw/display/edid-generate.c @@ -423,3 +423,17 @@ void qemu_edid_generate(uint8_t *edid, size_t size, edid_checksum(dta); } } + +size_t qemu_edid_size(uint8_t *edid) +{ + uint32_t exts; + + if (edid[0] != 0x00 || + edid[1] != 0xff) { + /* doesn't look like a valid edid block */ + return 0; + } + + exts = edid[126]; + return 128 * (exts + 1); +} diff --git a/include/hw/display/edid.h b/include/hw/display/edid.h index 63b60015c3..96910ada0f 100644 --- a/include/hw/display/edid.h +++ b/include/hw/display/edid.h @@ -14,5 +14,6 @@ typedef struct qemu_edid_info { void qemu_edid_generate(uint8_t *edid, size_t size, qemu_edid_info *info); +size_t qemu_edid_size(uint8_t *edid); #endif /* EDID_H */ -- cgit 1.4.1 From 97917e9e02e04bbb5f3b14c0f2b58913ef5f09d2 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 25 Sep 2018 09:56:44 +0200 Subject: display/edid: add region helper. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Create a io region for an EDID data block. Signed-off-by: Gerd Hoffmann Reviewed-by: Philippe Mathieu-Daudé Message-id: 20180925075646.25114-4-kraxel@redhat.com --- hw/display/Makefile.objs | 1 + hw/display/edid-region.c | 33 +++++++++++++++++++++++++++++++++ include/hw/display/edid.h | 4 ++++ 3 files changed, 38 insertions(+) create mode 100644 hw/display/edid-region.c (limited to 'include') diff --git a/hw/display/Makefile.objs b/hw/display/Makefile.objs index 492404c09e..780a76b9f0 100644 --- a/hw/display/Makefile.objs +++ b/hw/display/Makefile.objs @@ -15,6 +15,7 @@ common-obj-$(CONFIG_XEN) += xenfb.o common-obj-$(CONFIG_VGA_PCI) += vga-pci.o common-obj-$(CONFIG_VGA_PCI) += bochs-display.o +common-obj-$(CONFIG_VGA_PCI) += edid-region.o common-obj-$(CONFIG_VGA_ISA) += vga-isa.o common-obj-$(CONFIG_VGA_ISA_MM) += vga-isa-mm.o common-obj-$(CONFIG_VMWARE_VGA) += vmware_vga.o diff --git a/hw/display/edid-region.c b/hw/display/edid-region.c new file mode 100644 index 0000000000..9a15734d3a --- /dev/null +++ b/hw/display/edid-region.c @@ -0,0 +1,33 @@ +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "hw/display/edid.h" + +static uint64_t edid_region_read(void *ptr, hwaddr addr, unsigned size) +{ + uint8_t *edid = ptr; + + return edid[addr]; +} + +static void edid_region_write(void *ptr, hwaddr addr, + uint64_t val, unsigned size) +{ + /* read only */ +} + +static const MemoryRegionOps edid_region_ops = { + .read = edid_region_read, + .write = edid_region_write, + .valid.min_access_size = 1, + .valid.max_access_size = 4, + .impl.min_access_size = 1, + .impl.max_access_size = 1, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +void qemu_edid_region_io(MemoryRegion *region, Object *owner, + uint8_t *edid, size_t size) +{ + memory_region_init_io(region, owner, &edid_region_ops, + edid, "edid", size); +} diff --git a/include/hw/display/edid.h b/include/hw/display/edid.h index 96910ada0f..b7fe56a958 100644 --- a/include/hw/display/edid.h +++ b/include/hw/display/edid.h @@ -1,6 +1,8 @@ #ifndef EDID_H #define EDID_H +#include "hw/hw.h" + typedef struct qemu_edid_info { const char *vendor; const char *name; @@ -15,5 +17,7 @@ typedef struct qemu_edid_info { void qemu_edid_generate(uint8_t *edid, size_t size, qemu_edid_info *info); size_t qemu_edid_size(uint8_t *edid); +void qemu_edid_region_io(MemoryRegion *region, Object *owner, + uint8_t *edid, size_t size); #endif /* EDID_H */ -- cgit 1.4.1 From 06510b899fbb43a709ddb5ba04610efa7fbef13b Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 25 Sep 2018 09:56:45 +0200 Subject: display/edid: add DEFINE_EDID_PROPERTIES Add a define for edid monitor properties. Signed-off-by: Gerd Hoffmann Message-id: 20180925075646.25114-5-kraxel@redhat.com --- include/hw/display/edid.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include') diff --git a/include/hw/display/edid.h b/include/hw/display/edid.h index b7fe56a958..bd51d26916 100644 --- a/include/hw/display/edid.h +++ b/include/hw/display/edid.h @@ -20,4 +20,8 @@ size_t qemu_edid_size(uint8_t *edid); void qemu_edid_region_io(MemoryRegion *region, Object *owner, uint8_t *edid, size_t size); +#define DEFINE_EDID_PROPERTIES(_state, _edid_info) \ + DEFINE_PROP_UINT32("xres", _state, _edid_info.prefx, 0), \ + DEFINE_PROP_UINT32("yres", _state, _edid_info.prefy, 0) + #endif /* EDID_H */ -- cgit 1.4.1