Commit 01f23459 authored by Gerd Hoffmann's avatar Gerd Hoffmann

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: default avatarGerd Hoffmann <kraxel@redhat.com>
Acked-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/20181029205048.13200-1-kraxel@redhat.com
parent cf6d100d
...@@ -66,6 +66,7 @@ struct bochs_device { ...@@ -66,6 +66,7 @@ struct bochs_device {
u16 yres_virtual; u16 yres_virtual;
u32 stride; u32 stride;
u32 bpp; u32 bpp;
struct edid *edid;
/* drm */ /* drm */
struct drm_device *dev; struct drm_device *dev;
...@@ -126,6 +127,7 @@ void bochs_hw_setmode(struct bochs_device *bochs, ...@@ -126,6 +127,7 @@ void bochs_hw_setmode(struct bochs_device *bochs,
const struct drm_format_info *format); const struct drm_format_info *format);
void bochs_hw_setbase(struct bochs_device *bochs, void bochs_hw_setbase(struct bochs_device *bochs,
int x, int y, u64 addr); int x, int y, u64 addr);
int bochs_hw_load_edid(struct bochs_device *bochs);
/* bochs_mm.c */ /* bochs_mm.c */
int bochs_mm_init(struct bochs_device *bochs); int bochs_mm_init(struct bochs_device *bochs);
......
...@@ -69,6 +69,35 @@ static void bochs_hw_set_little_endian(struct bochs_device *bochs) ...@@ -69,6 +69,35 @@ static void bochs_hw_set_little_endian(struct bochs_device *bochs)
#define bochs_hw_set_native_endian(_b) bochs_hw_set_little_endian(_b) #define bochs_hw_set_native_endian(_b) bochs_hw_set_little_endian(_b)
#endif #endif
static int bochs_get_edid_block(void *data, u8 *buf,
unsigned int block, size_t len)
{
struct bochs_device *bochs = data;
size_t i, start = block * EDID_LENGTH;
if (start + len > 0x400 /* vga register offset */)
return -1;
for (i = 0; i < len; i++) {
buf[i] = readb(bochs->mmio + start + i);
}
return 0;
}
int bochs_hw_load_edid(struct bochs_device *bochs)
{
if (!bochs->mmio)
return -1;
kfree(bochs->edid);
bochs->edid = drm_do_get_edid(&bochs->connector,
bochs_get_edid_block, bochs);
if (bochs->edid == NULL)
return -1;
return 0;
}
int bochs_hw_init(struct drm_device *dev) int bochs_hw_init(struct drm_device *dev)
{ {
struct bochs_device *bochs = dev->dev_private; struct bochs_device *bochs = dev->dev_private;
...@@ -164,6 +193,7 @@ void bochs_hw_fini(struct drm_device *dev) ...@@ -164,6 +193,7 @@ void bochs_hw_fini(struct drm_device *dev)
if (bochs->fb_map) if (bochs->fb_map)
iounmap(bochs->fb_map); iounmap(bochs->fb_map);
pci_release_regions(dev->pdev); pci_release_regions(dev->pdev);
kfree(bochs->edid);
} }
void bochs_hw_setmode(struct bochs_device *bochs, void bochs_hw_setmode(struct bochs_device *bochs,
......
...@@ -213,10 +213,17 @@ static void bochs_encoder_init(struct drm_device *dev) ...@@ -213,10 +213,17 @@ static void bochs_encoder_init(struct drm_device *dev)
static int bochs_connector_get_modes(struct drm_connector *connector) static int bochs_connector_get_modes(struct drm_connector *connector)
{ {
int count; struct bochs_device *bochs =
container_of(connector, struct bochs_device, connector);
int count = 0;
if (bochs->edid)
count = drm_add_edid_modes(connector, bochs->edid);
if (!count) {
count = drm_add_modes_noedid(connector, 8192, 8192); count = drm_add_modes_noedid(connector, 8192, 8192);
drm_set_preferred_mode(connector, defx, defy); drm_set_preferred_mode(connector, defx, defy);
}
return count; return count;
} }
...@@ -271,6 +278,13 @@ static void bochs_connector_init(struct drm_device *dev) ...@@ -271,6 +278,13 @@ static void bochs_connector_init(struct drm_device *dev)
drm_connector_helper_add(connector, drm_connector_helper_add(connector,
&bochs_connector_connector_helper_funcs); &bochs_connector_connector_helper_funcs);
drm_connector_register(connector); drm_connector_register(connector);
bochs_hw_load_edid(bochs);
if (bochs->edid) {
DRM_INFO("Found EDID data blob.\n");
drm_connector_attach_edid_property(connector);
drm_connector_update_edid_property(connector, bochs->edid);
}
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment