aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/display/bcm2835_fb.c28
-rw-r--r--hw/misc/bcm2835_property.c21
2 files changed, 37 insertions, 12 deletions
diff --git a/hw/display/bcm2835_fb.c b/hw/display/bcm2835_fb.c
index a6c0a0cc94..76a10072b4 100644
--- a/hw/display/bcm2835_fb.c
+++ b/hw/display/bcm2835_fb.c
@@ -126,6 +126,18 @@ static void draw_line_src16(void *opaque, uint8_t *dst, const uint8_t *src,
}
}
+static bool fb_use_offsets(BCM2835FBConfig *config)
+{
+ /*
+ * Return true if we should use the viewport offsets.
+ * Experimentally, the hardware seems to do this only if the
+ * viewport size is larger than the physical screen. (It doesn't
+ * prevent the guest setting this silly viewport setting, though...)
+ */
+ return config->xres_virtual > config->xres &&
+ config->yres_virtual > config->yres;
+}
+
static void fb_update_display(void *opaque)
{
BCM2835FBState *s = opaque;
@@ -134,12 +146,18 @@ static void fb_update_display(void *opaque)
int last = 0;
int src_width = 0;
int dest_width = 0;
+ uint32_t xoff = 0, yoff = 0;
if (s->lock || !s->config.xres) {
return;
}
src_width = bcm2835_fb_get_pitch(&s->config);
+ if (fb_use_offsets(&s->config)) {
+ xoff = s->config.xoffset;
+ yoff = s->config.yoffset;
+ }
+
dest_width = s->config.xres;
switch (surface_bits_per_pixel(surface)) {
@@ -165,8 +183,9 @@ static void fb_update_display(void *opaque)
}
if (s->invalidate) {
+ hwaddr base = s->config.base + xoff + yoff * src_width;
framebuffer_update_memory_section(&s->fbsection, s->dma_mr,
- s->config.base,
+ base,
s->config.yres, src_width);
}
@@ -176,7 +195,8 @@ static void fb_update_display(void *opaque)
draw_line_src16, s, &first, &last);
if (first >= 0) {
- dpy_gfx_update(s->con, 0, first, s->config.xres, last - first + 1);
+ dpy_gfx_update(s->con, 0, first, s->config.xres,
+ last - first + 1);
}
s->invalidate = false;
@@ -202,8 +222,6 @@ static void bcm2835_fb_mbox_push(BCM2835FBState *s, uint32_t value)
s->config.base = s->vcram_base | (value & 0xc0000000);
s->config.base += BCM2835_FB_OFFSET;
- /* TODO - Manage properly virtual resolution */
-
pitch = bcm2835_fb_get_pitch(&s->config);
size = bcm2835_fb_get_size(&s->config);
@@ -224,8 +242,6 @@ void bcm2835_fb_reconfigure(BCM2835FBState *s, BCM2835FBConfig *newconfig)
s->config = *newconfig;
- /* TODO - Manage properly virtual resolution */
-
s->invalidate = true;
qemu_console_resize(s->con, s->config.xres, s->config.yres);
s->lock = false;
diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
index c8c4979bd2..e3ab677891 100644
--- a/hw/misc/bcm2835_property.c
+++ b/hw/misc/bcm2835_property.c
@@ -155,23 +155,32 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
case 0x00040002: /* Blank screen */
resplen = 4;
break;
- case 0x00040003: /* Get display width/height */
- case 0x00040004:
+ case 0x00040003: /* Get physical display width/height */
stl_le_phys(&s->dma_as, value + 12, fbconfig.xres);
stl_le_phys(&s->dma_as, value + 16, fbconfig.yres);
resplen = 8;
break;
- case 0x00044003: /* Test display width/height */
- case 0x00044004:
+ case 0x00040004: /* Get virtual display width/height */
+ stl_le_phys(&s->dma_as, value + 12, fbconfig.xres_virtual);
+ stl_le_phys(&s->dma_as, value + 16, fbconfig.yres_virtual);
resplen = 8;
break;
- case 0x00048003: /* Set display width/height */
- case 0x00048004:
+ case 0x00044003: /* Test physical display width/height */
+ case 0x00044004: /* Test virtual display width/height */
+ resplen = 8;
+ break;
+ case 0x00048003: /* Set physical display width/height */
fbconfig.xres = ldl_le_phys(&s->dma_as, value + 12);
fbconfig.yres = ldl_le_phys(&s->dma_as, value + 16);
fbconfig_updated = true;
resplen = 8;
break;
+ case 0x00048004: /* Set virtual display width/height */
+ fbconfig.xres_virtual = ldl_le_phys(&s->dma_as, value + 12);
+ fbconfig.yres_virtual = ldl_le_phys(&s->dma_as, value + 16);
+ fbconfig_updated = true;
+ resplen = 8;
+ break;
case 0x00040005: /* Get depth */
stl_le_phys(&s->dma_as, value + 12, fbconfig.bpp);
resplen = 4;