Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/bochs: add edid support.

Recent qemu (latest master branch, upcoming 3.1 release) got support
for EDID data. This patch adds guest driver support.

EDID support in qemu is not (yet) enabled by default, so please use
'qemu -device VGA,edid=on' for testing.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/20181029205048.13200-1-kraxel@redhat.com

+49 -3
+2
drivers/gpu/drm/bochs/bochs.h
··· 66 66 u16 yres_virtual; 67 67 u32 stride; 68 68 u32 bpp; 69 + struct edid *edid; 69 70 70 71 /* drm */ 71 72 struct drm_device *dev; ··· 127 126 const struct drm_format_info *format); 128 127 void bochs_hw_setbase(struct bochs_device *bochs, 129 128 int x, int y, u64 addr); 129 + int bochs_hw_load_edid(struct bochs_device *bochs); 130 130 131 131 /* bochs_mm.c */ 132 132 int bochs_mm_init(struct bochs_device *bochs);
+30
drivers/gpu/drm/bochs/bochs_hw.c
··· 69 69 #define bochs_hw_set_native_endian(_b) bochs_hw_set_little_endian(_b) 70 70 #endif 71 71 72 + static int bochs_get_edid_block(void *data, u8 *buf, 73 + unsigned int block, size_t len) 74 + { 75 + struct bochs_device *bochs = data; 76 + size_t i, start = block * EDID_LENGTH; 77 + 78 + if (start + len > 0x400 /* vga register offset */) 79 + return -1; 80 + 81 + for (i = 0; i < len; i++) { 82 + buf[i] = readb(bochs->mmio + start + i); 83 + } 84 + return 0; 85 + } 86 + 87 + int bochs_hw_load_edid(struct bochs_device *bochs) 88 + { 89 + if (!bochs->mmio) 90 + return -1; 91 + 92 + kfree(bochs->edid); 93 + bochs->edid = drm_do_get_edid(&bochs->connector, 94 + bochs_get_edid_block, bochs); 95 + if (bochs->edid == NULL) 96 + return -1; 97 + 98 + return 0; 99 + } 100 + 72 101 int bochs_hw_init(struct drm_device *dev) 73 102 { 74 103 struct bochs_device *bochs = dev->dev_private; ··· 193 164 if (bochs->fb_map) 194 165 iounmap(bochs->fb_map); 195 166 pci_release_regions(dev->pdev); 167 + kfree(bochs->edid); 196 168 } 197 169 198 170 void bochs_hw_setmode(struct bochs_device *bochs,
+17 -3
drivers/gpu/drm/bochs/bochs_kms.c
··· 213 213 214 214 static int bochs_connector_get_modes(struct drm_connector *connector) 215 215 { 216 - int count; 216 + struct bochs_device *bochs = 217 + container_of(connector, struct bochs_device, connector); 218 + int count = 0; 217 219 218 - count = drm_add_modes_noedid(connector, 8192, 8192); 219 - drm_set_preferred_mode(connector, defx, defy); 220 + if (bochs->edid) 221 + count = drm_add_edid_modes(connector, bochs->edid); 222 + 223 + if (!count) { 224 + count = drm_add_modes_noedid(connector, 8192, 8192); 225 + drm_set_preferred_mode(connector, defx, defy); 226 + } 220 227 return count; 221 228 } 222 229 ··· 278 271 drm_connector_helper_add(connector, 279 272 &bochs_connector_connector_helper_funcs); 280 273 drm_connector_register(connector); 274 + 275 + bochs_hw_load_edid(bochs); 276 + if (bochs->edid) { 277 + DRM_INFO("Found EDID data blob.\n"); 278 + drm_connector_attach_edid_property(connector); 279 + drm_connector_update_edid_property(connector, bochs->edid); 280 + } 281 281 } 282 282 283 283