@@ -46,8 +46,18 @@ virtio_gpu_base_fill_display_info(VirtIOGPUBase *g,
for (i = 0; i < g->conf.max_outputs; i++) {
if (g->enabled_output_bitmask & (1 << i)) {
dpy_info->pmodes[i].enabled = 1;
- dpy_info->pmodes[i].r.width = cpu_to_le32(g->req_state[i].width);
- dpy_info->pmodes[i].r.height = cpu_to_le32(g->req_state[i].height);
+ if (g->edid_info[i].maxx && g->edid_info[i].maxy &&
+ virtio_gpu_edid_enabled(g->conf)) {
+ dpy_info->pmodes[i].r.width =
+ cpu_to_le32(g->edid_info[i].maxx);
+ dpy_info->pmodes[i].r.height =
+ cpu_to_le32(g->edid_info[i].maxy);
+ } else {
+ dpy_info->pmodes[i].r.width =
+ cpu_to_le32(g->req_state[i].width);
+ dpy_info->pmodes[i].r.height =
+ cpu_to_le32(g->req_state[i].height);
+ }
}
}
}
@@ -62,6 +72,8 @@ virtio_gpu_base_generate_edid(VirtIOGPUBase *g, int scanout,
.prefx = g->req_state[scanout].width,
.prefy = g->req_state[scanout].height,
.refresh_rate = g->req_state[scanout].refresh_rate,
+ .maxx = g->req_state[scanout].width,
+ .maxy = g->req_state[scanout].height,
};
edid->size = cpu_to_le32(sizeof(edid->edid));
@@ -96,9 +108,16 @@ static void virtio_gpu_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info)
g->req_state[idx].x = info->xoff;
g->req_state[idx].y = info->yoff;
- g->req_state[idx].refresh_rate = info->refresh_rate;
- g->req_state[idx].width = info->width;
- g->req_state[idx].height = info->height;
+ if (!g->edid_info[idx].refresh_rate) {
+ g->req_state[idx].refresh_rate = info->refresh_rate;
+ }
+ if (!g->edid_info[idx].maxx) {
+ g->req_state[idx].width = info->width;
+ }
+ if (!g->edid_info[idx].maxy) {
+ g->req_state[idx].height = info->height;
+ }
+
g->req_state[idx].width_mm = info->width_mm;
g->req_state[idx].height_mm = info->height_mm;
@@ -204,11 +223,19 @@ virtio_gpu_base_device_realize(DeviceState *qdev,
g->enabled_output_bitmask = 1;
- g->req_state[0].width = g->conf.xres;
- g->req_state[0].height = g->conf.yres;
g->hw_ops = &virtio_gpu_ops;
for (i = 0; i < g->conf.max_outputs; i++) {
+ if (g->edid_info[i].maxx && g->edid_info[i].maxy &&
+ virtio_gpu_edid_enabled(g->conf) &&
+ g->edid_info[i].refresh_rate) {
+ g->req_state[i].refresh_rate = g->edid_info[i].refresh_rate;
+ g->req_state[i].width = g->edid_info[i].maxx;
+ g->req_state[i].height = g->edid_info[i].maxy;
+ } else {
+ g->req_state[i].width = g->conf.xres;
+ g->req_state[i].height = g->conf.yres;
+ }
g->scanout[i].con =
graphic_console_init(DEVICE(g), i, &virtio_gpu_ops, g);
}
@@ -1666,6 +1666,7 @@ static const VMStateDescription vmstate_virtio_gpu = {
static Property virtio_gpu_properties[] = {
VIRTIO_GPU_BASE_PROPERTIES(VirtIOGPU, parent_obj.conf),
+ VIRTIO_GPU_EDID_PROPERTIES_MULTI_DISPLAY(VirtIOGPU, parent_obj.edid_info),
DEFINE_PROP_SIZE("max_hostmem", VirtIOGPU, conf_max_hostmem,
256 * MiB),
DEFINE_PROP_BIT("blob", VirtIOGPU, parent_obj.conf.flags,
@@ -18,6 +18,7 @@
#include "ui/qemu-pixman.h"
#include "ui/console.h"
#include "hw/virtio/virtio.h"
+#include "hw/display/edid.h"
#include "qemu/log.h"
#include "sysemu/vhost-user-backend.h"
@@ -150,6 +151,7 @@ struct VirtIOGPUBase {
MemoryRegion hostmem;
struct virtio_gpu_scanout scanout[VIRTIO_GPU_MAX_SCANOUTS];
+ struct qemu_edid_info edid_info[VIRTIO_GPU_MAX_SCANOUTS];
int enabled_output_bitmask;
struct virtio_gpu_requested_state req_state[VIRTIO_GPU_MAX_SCANOUTS];
@@ -168,6 +170,30 @@ struct VirtIOGPUBaseClass {
DEFINE_PROP_UINT32("xres", _state, _conf.xres, 1280), \
DEFINE_PROP_UINT32("yres", _state, _conf.yres, 800)
+#define VIRTIO_GPU_EDID_PROPERTIES_MULTI_DISPLAY(_state, _edid_info) \
+ (VIRTIO_GPU_EDID_PROPERTIES(_state, _edid_info, 0), \
+ VIRTIO_GPU_EDID_PROPERTIES(_state, _edid_info, 1), \
+ VIRTIO_GPU_EDID_PROPERTIES(_state, _edid_info, 2), \
+ VIRTIO_GPU_EDID_PROPERTIES(_state, _edid_info, 3), \
+ VIRTIO_GPU_EDID_PROPERTIES(_state, _edid_info, 4), \
+ VIRTIO_GPU_EDID_PROPERTIES(_state, _edid_info, 5), \
+ VIRTIO_GPU_EDID_PROPERTIES(_state, _edid_info, 6), \
+ VIRTIO_GPU_EDID_PROPERTIES(_state, _edid_info, 7), \
+ VIRTIO_GPU_EDID_PROPERTIES(_state, _edid_info, 8), \
+ VIRTIO_GPU_EDID_PROPERTIES(_state, _edid_info, 9), \
+ VIRTIO_GPU_EDID_PROPERTIES(_state, _edid_info, 10), \
+ VIRTIO_GPU_EDID_PROPERTIES(_state, _edid_info, 11), \
+ VIRTIO_GPU_EDID_PROPERTIES(_state, _edid_info, 12), \
+ VIRTIO_GPU_EDID_PROPERTIES(_state, _edid_info, 13), \
+ VIRTIO_GPU_EDID_PROPERTIES(_state, _edid_info, 14), \
+ VIRTIO_GPU_EDID_PROPERTIES(_state, _edid_info, 15)) \
+
+#define VIRTIO_GPU_EDID_PROPERTIES(_state, _edid_info, id) \
+ (DEFINE_PROP_UINT32("maxx" #id, _state, _edid_info[id].maxx, 0), \
+ DEFINE_PROP_UINT32("maxy" #id, _state, _edid_info[id].maxy, 0), \
+ DEFINE_PROP_UINT32("refresh_rate" #id, _state, \
+ _edid_info[id].refresh_rate, 0))
+
typedef struct VGPUDMABuf {
QemuDmaBuf *buf;
uint32_t scanout_id;
customize refresh rate and resolution for the guest VM instead of being limited by the actual resolution of the host. add edid info and modify conf like: "-device", "virtio-vga-gl,edid=on,max_outputs=2, refresh_rate0=120000,maxx0=7680,maxy0=1080,refresh_rate1=75000, maxx1=3840,maxy1=960" Change-Id: I5d5742d280186ffd5dee9eba7697f06a2b09b123 Signed-off-by: Lei Huang <Lei.Huang@amd.com> --- hw/display/virtio-gpu-base.c | 41 ++++++++++++++++++++++++++++------ hw/display/virtio-gpu.c | 1 + include/hw/virtio/virtio-gpu.h | 26 +++++++++++++++++++++ 3 files changed, 61 insertions(+), 7 deletions(-)