--- a/include/hw/virtio/virtio-gpu.h +++ b/include/hw/virtio/virtio-gpu.h @@ -128,6 +128,7 @@ uint32_t flags; uint32_t xres; uint32_t yres; + uint32_t refresh_rate; uint64_t hostmem; VirtIOGPUOutputList *outputs; }; @@ -173,7 +174,8 @@ DEFINE_PROP_BIT("edid", _state, _conf.flags, \ VIRTIO_GPU_FLAG_EDID_ENABLED, true), \ DEFINE_PROP_UINT32("xres", _state, _conf.xres, 1280), \ - DEFINE_PROP_UINT32("yres", _state, _conf.yres, 800) + DEFINE_PROP_UINT32("yres", _state, _conf.yres, 800), \ + DEFINE_PROP_UINT32("refresh_rate", _state, _conf.refresh_rate, 0) typedef struct VGPUDMABuf { QemuDmaBuf *buf; --- a/hw/display/virtio-gpu-base.c +++ b/hw/display/virtio-gpu-base.c @@ -64,7 +64,9 @@ .height_mm = g->req_state[scanout].height_mm, .prefx = g->req_state[scanout].width, .prefy = g->req_state[scanout].height, - .refresh_rate = g->req_state[scanout].refresh_rate, + /* An explicit monitor refresh rate, in mHz, survives UI resizes. */ + .refresh_rate = g->conf.refresh_rate ? g->conf.refresh_rate : + g->req_state[scanout].refresh_rate, }; for (output_idx = 0, node = g->conf.outputs; --- a/hw/display/edid-generate.c +++ b/hw/display/edid-generate.c @@ -220,17 +220,17 @@ desc[5 + len] = '\n'; } -static void edid_desc_ranges(uint8_t *desc) +static void edid_desc_ranges(uint8_t *desc, uint32_t refresh_rate, + uint32_t horizontal_rate) { edid_desc_type(desc, 0xfd); - /* vertical (50 -> 125 Hz) */ - desc[5] = 50; - desc[6] = 125; - - /* horizontal (30 -> 160 kHz) */ - desc[7] = 30; - desc[8] = 160; + /* Preserve the legacy ranges and include the preferred mode. */ + desc[5] = 50; + desc[6] = MIN(255, MAX(125, DIV_ROUND_UP(refresh_rate, 1000))); + + desc[7] = 30; + desc[8] = MIN(255, MAX(160, DIV_ROUND_UP(horizontal_rate, 1000))); /* max dot clock (2550 MHz) */ desc[9] = 2550 / 10; @@ -513,7 +513,8 @@ * so dta descriptor offsets don't move any more. */ - edid_desc_ranges(desc); + edid_desc_ranges(desc, refresh_rate, + timings.clock * 10000 / (info->prefx + timings.xblank)); desc = edid_desc_next(edid, dta, desc); if (desc && info->name) {