[PATCH v1] dm: vdisplay: 4K support.


Sun, Peng
 

From: Sun Peng <peng.p.sun@...>

Add 3820x2160@60 mode to EDID data of vdisplay.

Signed-off-by: Sun Peng <peng.p.sun@...>
---
devicemodel/hw/pci/virtio/virtio_gpu.c | 5 ++--
devicemodel/hw/vdisplay_sdl.c | 41 +++++++++++++++++++++++++-
2 files changed, 42 insertions(+), 4 deletions(-)

diff --git a/devicemodel/hw/pci/virtio/virtio_gpu.c b/devicemodel/hw/pci/virtio/virtio_gpu.c
index 0b79d2ddb..73cb08584 100644
--- a/devicemodel/hw/pci/virtio/virtio_gpu.c
+++ b/devicemodel/hw/pci/virtio/virtio_gpu.c
@@ -74,7 +74,7 @@
#define VIRTIO_GPU_FLAG_FENCE (1 << 0)
#define VIRTIO_GPU_VGA_FB_SIZE 16 * MB
#define VIRTIO_GPU_VGA_DMEMSZ 128
-#define VIRTIO_GPU_EDID_SIZE 384
+#define VIRTIO_GPU_EDID_SIZE 256
#define VIRTIO_GPU_VGA_IOPORT_OFFSET 0x400
#define VIRTIO_GPU_VGA_IOPORT_SIZE (0x3e0 - 0x3c0)
#define VIRTIO_GPU_VGA_VBE_OFFSET 0x500
@@ -571,8 +571,7 @@ virtio_gpu_cmd_get_edid(struct virtio_gpu_command *cmd)
memcpy(cmd->iov[1].iov_base, &resp, sizeof(resp));
return;
}
- /* Only one EDID block is enough */
- resp.size = 128;
+ resp.size = VIRTIO_GPU_EDID_SIZE;
resp.hdr.type = VIRTIO_GPU_RESP_OK_EDID;
vdpy_get_edid(gpu->vdpy_handle, req.scanout, resp.edid, resp.size);
memcpy(cmd->iov[1].iov_base, &resp, sizeof(resp));
diff --git a/devicemodel/hw/vdisplay_sdl.c b/devicemodel/hw/vdisplay_sdl.c
index ed1edf86f..ff51c745d 100644
--- a/devicemodel/hw/vdisplay_sdl.c
+++ b/devicemodel/hw/vdisplay_sdl.c
@@ -33,6 +33,8 @@
#define VDPY_MIN_HEIGHT 480
#define transto_10bits(color) (uint16_t)(color * 1024 + 0.5)
#define VSCREEN_MAX_NUM 2
+#define EDID_BASIC_BLOCK_SIZE 128
+#define EDID_CEA861_EXT_BLOCK_SIZE 128

static unsigned char default_raw_argb[VDPY_DEFAULT_WIDTH * VDPY_DEFAULT_HEIGHT * 4];

@@ -108,6 +110,7 @@ typedef enum {
ESTT = 1, // Established Timings I & II
STDT, // Standard Timings
ESTT3, // Established Timings III
+ CEA861, // CEA-861 Timings
} TIMING_MODE;

static const struct timing_entry {
@@ -118,6 +121,8 @@ static const struct timing_entry {
uint32_t bit; // bit idx
uint8_t hz; // frequency
bool is_std; // the flag of standard mode
+ bool is_cea861; // CEA-861 timings
+ uint8_t vic; // Video Indentification Code
} timings[] = {
/* Established Timings I & II (all @ 60Hz) */
{ .hpixel = 1280, .vpixel = 1024, .byte = 36, .bit = 0, .hz = 75},
@@ -132,6 +137,9 @@ static const struct timing_entry {
{ .hpixel = 1600, .vpixel = 1200, .hz = 60, .is_std = true },
{ .hpixel = 1600, .vpixel = 900, .hz = 60, .is_std = true },
{ .hpixel = 1440, .vpixel = 900, .hz = 60, .is_std = true },
+
+ /* CEA-861 Timings */
+ { .hpixel = 3840, .vpixel = 2160, .hz = 60, .is_cea861 = true, .vic = 97 },
};

typedef struct frame_param{
@@ -243,7 +251,7 @@ vdpy_edid_set_color(uint8_t *edid, float red_x, float red_y,
color[9] = wy >> 2;
}

-static void
+static uint8_t
vdpy_edid_set_timing(uint8_t *addr, TIMING_MODE mode)
{
static uint16_t idx;
@@ -252,8 +260,10 @@ vdpy_edid_set_timing(uint8_t *addr, TIMING_MODE mode)
uint8_t stdcnt;
uint16_t hpixel;
int16_t AR;
+ uint8_t num_timings;

stdcnt = 0;
+ num_timings = 0;

if(mode == STDT) {
addr += 38;
@@ -318,6 +328,13 @@ vdpy_edid_set_timing(uint8_t *addr, TIMING_MODE mode)
continue;
}
break;
+ case CEA861: // CEA-861 Timings
+ if (timing->is_cea861) {
+ addr[0] = timing->vic;
+ addr += 1;
+ num_timings++;
+ }
+ break;
default:
continue;
}
@@ -328,6 +345,8 @@ vdpy_edid_set_timing(uint8_t *addr, TIMING_MODE mode)
addr += 2;
stdcnt++;
}
+
+ return num_timings;
}

static void
@@ -438,6 +457,7 @@ vdpy_edid_generate(uint8_t *edid, size_t size, struct edid_info *info)
uint32_t serial;
uint8_t *desc;
base_param b_param;
+ uint8_t num_cea_timings;

vdpy_edid_set_baseparam(&b_param, info->prefx, info->prefy);

@@ -519,6 +539,25 @@ vdpy_edid_generate(uint8_t *edid, size_t size, struct edid_info *info)

/* Checksum */
edid[127] = vdpy_edid_get_checksum(edid);
+
+ if (size >= (EDID_BASIC_BLOCK_SIZE + EDID_CEA861_EXT_BLOCK_SIZE)) {
+ edid[126] = 1;
+ edid[127] = vdpy_edid_get_checksum(edid);
+
+ // CEA EDID Extension
+ edid[EDID_BASIC_BLOCK_SIZE + 0] = 0x02;
+ // Revision Number
+ edid[EDID_BASIC_BLOCK_SIZE + 1] = 0x03;
+ // SVDs
+ edid[EDID_BASIC_BLOCK_SIZE + 4] |= 0x02 << 5;
+ desc = edid + EDID_BASIC_BLOCK_SIZE + 5;
+ num_cea_timings = vdpy_edid_set_timing(desc, CEA861);
+ edid[EDID_BASIC_BLOCK_SIZE + 4] |= num_cea_timings;
+ edid[EDID_BASIC_BLOCK_SIZE + 2] |= 5 + num_cea_timings;
+
+ desc = edid + EDID_BASIC_BLOCK_SIZE;
+ edid[EDID_BASIC_BLOCK_SIZE + 127] = vdpy_edid_get_checksum(desc);
+ }
}

void
--
2.25.1