Also included are overall modesetting improvements

Signed-off-by: Jakob Bornecrantz <ja...@vmware.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.c  |    9 ++++
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.h  |    5 ++
 drivers/gpu/drm/vmwgfx/vmwgfx_fb.c   |   81 ++++++++++++----------------------
 drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c |   18 ++++++++
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c  |   68 +++++++++++-----------------
 drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c  |   70 ++++++++++++++++++++++++-----
 6 files changed, 144 insertions(+), 107 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index a6e8f68..5268af2 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -318,6 +318,15 @@ static int vmw_driver_load(struct drm_device *dev, 
unsigned long chipset)
                goto out_err3;
        }
 
+       /* need mmio memory to check for fifo pitchlock cap */
+       if (!(dev_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) &&
+           !(dev_priv->capabilities & SVGA_CAP_PITCHLOCK) &&
+           !vmw_fifo_have_pitchlock(dev_priv)) {
+               ret = -ENOSYS;
+               DRM_ERROR("Hardware has no pitchlock\n");
+               goto out_err4;
+       }
+
        dev_priv->tdev = ttm_object_device_init
            (dev_priv->mem_global_ref.object, 12);
 
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h 
b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 356dc93..fdcc1d6 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -179,6 +179,7 @@ struct vmw_private {
        uint32_t vga_red_mask;
        uint32_t vga_blue_mask;
        uint32_t vga_green_mask;
+       uint32_t vga_pitchlock;
 
        /*
         * Framebuffer info.
@@ -393,6 +394,7 @@ extern int vmw_fifo_send_fence(struct vmw_private *dev_priv,
 extern void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason);
 extern int vmw_fifo_mmap(struct file *filp, struct vm_area_struct *vma);
 extern bool vmw_fifo_have_3d(struct vmw_private *dev_priv);
+extern bool vmw_fifo_have_pitchlock(struct vmw_private *dev_priv);
 
 /**
  * TTM glue - vmwgfx_ttm_glue.c
@@ -466,6 +468,9 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf,
                          struct ttm_object_file *tfile,
                          struct ttm_buffer_object *bo,
                          SVGA3dCmdHeader *header);
+void vmw_kms_write_svga(struct vmw_private *vmw_priv,
+                       unsigned width, unsigned height, unsigned pitch,
+                       unsigned bbp, unsigned depth);
 
 /**
  * Overlay control - vmwgfx_overlay.c
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
index 9822ee6..c1eae30 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
@@ -135,16 +135,14 @@ static int vmw_fb_check_var(struct fb_var_screeninfo *var,
                return -EINVAL;
        }
 
-       /* without multimon its hard to resize */
-       if (!(vmw_priv->capabilities & SVGA_CAP_MULTIMON) &&
-           (var->xres != par->max_width ||
-            var->yres != par->max_height)) {
-               DRM_ERROR("Tried to resize, but we don't have multimon\n");
+       if (!(vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) &&
+           (var->xoffset != 0 || var->yoffset != 0)) {
+               DRM_ERROR("Can not handle panning without display topology\n");
                return -EINVAL;
        }
 
-       if (var->xres > par->max_width ||
-           var->yres > par->max_height) {
+       if ((var->xoffset + var->xres) > par->max_width ||
+           (var->yoffset + var->yres) > par->max_height) {
                DRM_ERROR("Requested geom can not fit in framebuffer\n");
                return -EINVAL;
        }
@@ -157,8 +155,8 @@ static int vmw_fb_set_par(struct fb_info *info)
        struct vmw_fb_par *par = info->par;
        struct vmw_private *vmw_priv = par->vmw_priv;
 
-       if (vmw_priv->capabilities & SVGA_CAP_MULTIMON) {
-               vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
+       if (vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) {
+               vmw_write(vmw_priv, SVGA_REG_ENABLE, 0);
                vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0);
                vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
                vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
@@ -167,18 +165,11 @@ static int vmw_fb_set_par(struct fb_info *info)
                vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
                vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
 
-               vmw_write(vmw_priv, SVGA_REG_ENABLE, 1);
-               vmw_write(vmw_priv, SVGA_REG_WIDTH, par->max_width);
-               vmw_write(vmw_priv, SVGA_REG_HEIGHT, par->max_height);
-               vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, par->bpp);
-               vmw_write(vmw_priv, SVGA_REG_DEPTH, par->depth);
-               vmw_write(vmw_priv, SVGA_REG_RED_MASK, 0x00ff0000);
-               vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
-               vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
+               vmw_kms_write_svga(vmw_priv, info->var.xres, info->var.yres,
+                                  info->fix.line_length,
+                                  par->bpp, par->depth);
 
                /* TODO check if pitch and offset changes */
-
-               vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
                vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0);
                vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
                vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, 
info->var.xoffset);
@@ -186,13 +177,22 @@ static int vmw_fb_set_par(struct fb_info *info)
                vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, info->var.xres);
                vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, info->var.yres);
                vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
+               vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
+               vmw_write(vmw_priv, SVGA_REG_ENABLE, 1);
        } else {
-               vmw_write(vmw_priv, SVGA_REG_WIDTH, info->var.xres);
-               vmw_write(vmw_priv, SVGA_REG_HEIGHT, info->var.yres);
+               vmw_write(vmw_priv, SVGA_REG_ENABLE, 0);
+               vmw_kms_write_svga(vmw_priv, info->var.xres, info->var.yres,
+                                  info->fix.line_length,
+                                  par->bpp, par->depth);
+               vmw_write(vmw_priv, SVGA_REG_ENABLE, 1);
 
-               /* TODO check if pitch and offset changes */
        }
 
+       /* This is really helpfull as if this is fails the user
+        * can probably not see anything on the screen.
+        */
+       WARN_ON(vmw_read(vmw_priv, SVGA_REG_FB_OFFSET) != 0);
+
        return 0;
 }
 
@@ -434,48 +434,23 @@ int vmw_fb_init(struct vmw_private *vmw_priv)
        unsigned fb_bbp, fb_depth, fb_offset, fb_pitch, fb_size;
        int ret;
 
+       /* XXX these shouldn't be hardcoded */
        initial_width = 800;
        initial_height = 600;
 
        fb_bbp = 32;
        fb_depth = 24;
 
-       if (vmw_priv->capabilities & SVGA_CAP_MULTIMON) {
-               fb_width = min(vmw_priv->fb_max_width, (unsigned)2048);
-               fb_height = min(vmw_priv->fb_max_height, (unsigned)2048);
-       } else {
-               fb_width = min(vmw_priv->fb_max_width, initial_width);
-               fb_height = min(vmw_priv->fb_max_height, initial_height);
-       }
+       /* XXX as shouldn't these be as well */
+       fb_width = min(vmw_priv->fb_max_width, (unsigned)2048);
+       fb_height = min(vmw_priv->fb_max_height, (unsigned)2048);
 
        initial_width = min(fb_width, initial_width);
        initial_height = min(fb_height, initial_height);
 
-       vmw_write(vmw_priv, SVGA_REG_WIDTH, fb_width);
-       vmw_write(vmw_priv, SVGA_REG_HEIGHT, fb_height);
-       vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, fb_bbp);
-       vmw_write(vmw_priv, SVGA_REG_DEPTH, fb_depth);
-       vmw_write(vmw_priv, SVGA_REG_RED_MASK, 0x00ff0000);
-       vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
-       vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
-
-       fb_size = vmw_read(vmw_priv, SVGA_REG_FB_SIZE);
+       fb_pitch = fb_width * fb_bbp / 8;
+       fb_size = fb_pitch * fb_height;
        fb_offset = vmw_read(vmw_priv, SVGA_REG_FB_OFFSET);
-       fb_pitch = vmw_read(vmw_priv, SVGA_REG_BYTES_PER_LINE);
-
-       DRM_DEBUG("width  %u\n", vmw_read(vmw_priv, SVGA_REG_MAX_WIDTH));
-       DRM_DEBUG("height %u\n", vmw_read(vmw_priv, SVGA_REG_MAX_HEIGHT));
-       DRM_DEBUG("width  %u\n", vmw_read(vmw_priv, SVGA_REG_WIDTH));
-       DRM_DEBUG("height %u\n", vmw_read(vmw_priv, SVGA_REG_HEIGHT));
-       DRM_DEBUG("bpp    %u\n", vmw_read(vmw_priv, SVGA_REG_BITS_PER_PIXEL));
-       DRM_DEBUG("depth  %u\n", vmw_read(vmw_priv, SVGA_REG_DEPTH));
-       DRM_DEBUG("bpl    %u\n", vmw_read(vmw_priv, SVGA_REG_BYTES_PER_LINE));
-       DRM_DEBUG("r mask %08x\n", vmw_read(vmw_priv, SVGA_REG_RED_MASK));
-       DRM_DEBUG("g mask %08x\n", vmw_read(vmw_priv, SVGA_REG_GREEN_MASK));
-       DRM_DEBUG("b mask %08x\n", vmw_read(vmw_priv, SVGA_REG_BLUE_MASK));
-       DRM_DEBUG("fb_offset 0x%08x\n", fb_offset);
-       DRM_DEBUG("fb_pitch  %u\n", fb_pitch);
-       DRM_DEBUG("fb_size   %u kiB\n", fb_size / 1024);
 
        info = framebuffer_alloc(sizeof(*par), device);
        if (!info)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
index 39d43a0..8720b01 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
@@ -34,6 +34,9 @@ bool vmw_fifo_have_3d(struct vmw_private *dev_priv)
        __le32 __iomem *fifo_mem = dev_priv->mmio_virt;
        uint32_t fifo_min, hwversion;
 
+       if (!(dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO))
+               return false;
+
        fifo_min = ioread32(fifo_mem  + SVGA_FIFO_MIN);
        if (fifo_min <= SVGA_FIFO_3D_HWVERSION * sizeof(unsigned int))
                return false;
@@ -48,6 +51,21 @@ bool vmw_fifo_have_3d(struct vmw_private *dev_priv)
        return true;
 }
 
+bool vmw_fifo_have_pitchlock(struct vmw_private *dev_priv)
+{
+       __le32 __iomem *fifo_mem = dev_priv->mmio_virt;
+       uint32_t caps;
+
+       if (!(dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO))
+               return false;
+
+       caps = ioread32(fifo_mem + SVGA_FIFO_CAPABILITIES);
+       if (caps & SVGA_FIFO_CAP_PITCHLOCK)
+               return true;
+
+       return false;
+}
+
 int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
 {
        __le32 __iomem *fifo_mem = dev_priv->mmio_virt;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 31f9afe..05d2fa0 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -596,31 +596,11 @@ static int vmw_framebuffer_dmabuf_pin(struct 
vmw_framebuffer *vfb)
                vmw_framebuffer_to_vfbd(&vfb->base);
        int ret;
 
+
        vmw_overlay_pause_all(dev_priv);
 
        ret = vmw_dmabuf_to_start_of_vram(dev_priv, vfbd->buffer);
 
-       if (dev_priv->capabilities & SVGA_CAP_MULTIMON) {
-               vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, 0);
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_Y, 0);
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_WIDTH, 0);
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
-
-               vmw_write(dev_priv, SVGA_REG_ENABLE, 1);
-               vmw_write(dev_priv, SVGA_REG_WIDTH, vfb->base.width);
-               vmw_write(dev_priv, SVGA_REG_HEIGHT, vfb->base.height);
-               vmw_write(dev_priv, SVGA_REG_BITS_PER_PIXEL, 
vfb->base.bits_per_pixel);
-               vmw_write(dev_priv, SVGA_REG_DEPTH, vfb->base.depth);
-               vmw_write(dev_priv, SVGA_REG_RED_MASK, 0x00ff0000);
-               vmw_write(dev_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
-               vmw_write(dev_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
-       } else
-               WARN_ON(true);
-
        vmw_overlay_resume_all(dev_priv);
 
        return 0;
@@ -668,7 +648,7 @@ int vmw_kms_new_framebuffer_dmabuf(struct vmw_private 
*dev_priv,
 
        /* XXX get the first 3 from the surface info */
        vfbd->base.base.bits_per_pixel = 32;
-       vfbd->base.base.pitch = width * 32 / 4;
+       vfbd->base.base.pitch = width * vfbd->base.base.bits_per_pixel / 8;
        vfbd->base.base.depth = 24;
        vfbd->base.base.width = width;
        vfbd->base.base.height = height;
@@ -832,24 +812,25 @@ out:
        return ret;
 }
 
-int vmw_kms_save_vga(struct vmw_private *vmw_priv)
+void vmw_kms_write_svga(struct vmw_private *vmw_priv,
+                       unsigned width, unsigned height, unsigned pitch,
+                       unsigned bbp, unsigned depth)
 {
-       /*
-        * setup a single multimon monitor with the size
-        * of 0x0, this stops the UI from resizing when we
-        * change the framebuffer size
-        */
-       if (vmw_priv->capabilities & SVGA_CAP_MULTIMON) {
-               vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_Y, 0);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, 0);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
-       }
+       if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK)
+               vmw_write(vmw_priv, SVGA_REG_PITCHLOCK, pitch);
+       else if (vmw_fifo_have_pitchlock(vmw_priv))
+               iowrite32(pitch, vmw_priv->mmio_virt + SVGA_FIFO_PITCHLOCK);
+       vmw_write(vmw_priv, SVGA_REG_WIDTH, width);
+       vmw_write(vmw_priv, SVGA_REG_HEIGHT, height);
+       vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, bbp);
+       vmw_write(vmw_priv, SVGA_REG_DEPTH, depth);
+       vmw_write(vmw_priv, SVGA_REG_RED_MASK, 0x00ff0000);
+       vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
+       vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
+}
 
+int vmw_kms_save_vga(struct vmw_private *vmw_priv)
+{
        vmw_priv->vga_width = vmw_read(vmw_priv, SVGA_REG_WIDTH);
        vmw_priv->vga_height = vmw_read(vmw_priv, SVGA_REG_HEIGHT);
        vmw_priv->vga_bpp = vmw_read(vmw_priv, SVGA_REG_BITS_PER_PIXEL);
@@ -858,6 +839,10 @@ int vmw_kms_save_vga(struct vmw_private *vmw_priv)
        vmw_priv->vga_red_mask = vmw_read(vmw_priv, SVGA_REG_RED_MASK);
        vmw_priv->vga_green_mask = vmw_read(vmw_priv, SVGA_REG_GREEN_MASK);
        vmw_priv->vga_blue_mask = vmw_read(vmw_priv, SVGA_REG_BLUE_MASK);
+       if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK)
+               vmw_priv->vga_pitchlock = vmw_read(vmw_priv, 
SVGA_REG_PITCHLOCK);
+       else if (vmw_fifo_have_pitchlock(vmw_priv))
+               vmw_priv->vga_pitchlock = ioread32(vmw_priv->mmio_virt + 
SVGA_FIFO_PITCHLOCK);
 
        return 0;
 }
@@ -872,9 +857,10 @@ int vmw_kms_restore_vga(struct vmw_private *vmw_priv)
        vmw_write(vmw_priv, SVGA_REG_RED_MASK, vmw_priv->vga_red_mask);
        vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, vmw_priv->vga_green_mask);
        vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, vmw_priv->vga_blue_mask);
-
-       /* TODO check for multimon */
-       vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 0);
+       if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK)
+               vmw_write(vmw_priv, SVGA_REG_PITCHLOCK, 
vmw_priv->vga_pitchlock);
+       else if (vmw_fifo_have_pitchlock(vmw_priv))
+               iowrite32(vmw_priv->vga_pitchlock, vmw_priv->mmio_virt + 
SVGA_FIFO_PITCHLOCK);
 
        return 0;
 }
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index 9089159..b76bfe5 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -38,6 +38,7 @@ struct vmw_legacy_display {
        struct list_head active;
 
        unsigned num_active;
+       unsigned last_num_active;
 
        struct vmw_framebuffer *fb;
 };
@@ -88,12 +89,37 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
 {
        struct vmw_legacy_display *lds = dev_priv->ldu_priv;
        struct vmw_legacy_display_unit *entry;
-       struct drm_crtc *crtc;
+       struct drm_framebuffer *fb = NULL;
+       struct drm_crtc *crtc = NULL;
        int i = 0;
 
-       /* to stop the screen from changing size on resize */
-       vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 0);
-       for (i = 0; i < lds->num_active; i++) {
+       /* If there is no display topology the host just assumes
+        * that the guest will set the same layout as the host.
+        */
+       if (!(dev_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY)) {
+               int w = 0, h = 0;
+               list_for_each_entry(entry, &lds->active, active) {
+                       crtc = &entry->base.crtc;
+                       w = max(w, crtc->x + crtc->mode.hdisplay);
+                       h = max(h, crtc->y + crtc->mode.vdisplay);
+                       i++;
+               }
+
+               if (crtc == NULL)
+                       return 0;
+               fb = entry->base.crtc.fb;
+
+               vmw_write(dev_priv, SVGA_REG_ENABLE, 0);
+               vmw_kms_write_svga(dev_priv, w, h, fb->pitch,
+                                  fb->bits_per_pixel, fb->depth);
+               vmw_write(dev_priv, SVGA_REG_ENABLE, 1);
+
+               return 0;
+       }
+
+       vmw_write(dev_priv, SVGA_REG_ENABLE, 0);
+
+       for (i = 0; i < lds->last_num_active; i++) {
                vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, i);
                vmw_write(dev_priv, SVGA_REG_DISPLAY_IS_PRIMARY, !i);
                vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
@@ -103,8 +129,14 @@ static int vmw_ldu_commit_list(struct vmw_private 
*dev_priv)
                vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
        }
 
-       /* Now set the mode */
-       vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, lds->num_active);
+       if (!list_empty(&lds->active)) {
+               entry = list_entry(lds->active.next, typeof(*entry), active);
+               fb = entry->base.crtc.fb;
+
+               vmw_kms_write_svga(dev_priv, fb->width, fb->height, fb->pitch,
+                                  fb->bits_per_pixel, fb->depth);
+       }
+
        i = 0;
        list_for_each_entry(entry, &lds->active, active) {
                crtc = &entry->base.crtc;
@@ -120,6 +152,14 @@ static int vmw_ldu_commit_list(struct vmw_private 
*dev_priv)
                i++;
        }
 
+       /* Make sure we always show something */
+       vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, i ? i : 1);
+       vmw_write(dev_priv, SVGA_REG_ENABLE, 1);
+
+       BUG_ON(i != lds->num_active);
+
+       lds->last_num_active = lds->num_active;
+
        return 0;
 }
 
@@ -487,18 +527,22 @@ int vmw_kms_init_legacy_display_system(struct vmw_private 
*dev_priv)
 
        INIT_LIST_HEAD(&dev_priv->ldu_priv->active);
        dev_priv->ldu_priv->num_active = 0;
+       dev_priv->ldu_priv->last_num_active = 0;
        dev_priv->ldu_priv->fb = NULL;
 
        drm_mode_create_dirty_info_property(dev_priv->dev);
 
        vmw_ldu_init(dev_priv, 0);
-       vmw_ldu_init(dev_priv, 1);
-       vmw_ldu_init(dev_priv, 2);
-       vmw_ldu_init(dev_priv, 3);
-       vmw_ldu_init(dev_priv, 4);
-       vmw_ldu_init(dev_priv, 5);
-       vmw_ldu_init(dev_priv, 6);
-       vmw_ldu_init(dev_priv, 7);
+       /* for old hardware without multimon only enable one display */
+       if (dev_priv->capabilities & SVGA_CAP_MULTIMON) {
+               vmw_ldu_init(dev_priv, 1);
+               vmw_ldu_init(dev_priv, 2);
+               vmw_ldu_init(dev_priv, 3);
+               vmw_ldu_init(dev_priv, 4);
+               vmw_ldu_init(dev_priv, 5);
+               vmw_ldu_init(dev_priv, 6);
+               vmw_ldu_init(dev_priv, 7);
+       }
 
        return 0;
 }
-- 
1.6.0.4


------------------------------------------------------------------------------
SOLARIS 10 is the OS for Data Centers - provides features such as DTrace,
Predictive Self Healing and Award Winning ZFS. Get Solaris 10 NOW
http://p.sf.net/sfu/solaris-dev2dev
--
_______________________________________________
Dri-devel mailing list
Dri-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/dri-devel

Reply via email to