diff mbox series

[1/1] virtio-gpu: customize EDID for vms

Message ID 20240726055029.946-2-Lei.Huang@amd.com
State New
Headers show
Series Brief description of the patch series | expand

Commit Message

Lei Huang July 26, 2024, 5:50 a.m. UTC
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(-)
diff mbox series

Patch

diff --git a/hw/display/virtio-gpu-base.c b/hw/display/virtio-gpu-base.c
index 4fc7ef8896c..80d22005447 100644
--- a/hw/display/virtio-gpu-base.c
+++ b/hw/display/virtio-gpu-base.c
@@ -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);
     }
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 3281842bfe1..dd759a80522 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -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,
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 7a59379f5a7..094f2f65f71 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -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;