All of lore.kernel.org
 help / color / mirror / Atom feed
From: Thomas Hellstrom <thellstrom@vmware.com>
To: airlied@gmail.com
Cc: Thomas Hellstrom <thellstrom@vmware.com>,
	dri-devel@lists.freedesktop.org
Subject: [PATCH 06/13] drm/vmwgfx: Support older hardware.
Date: Tue, 27 Apr 2010 19:45:38 +0200	[thread overview]
Message-ID: <1272390345-3655-7-git-send-email-thellstrom@vmware.com> (raw)
In-Reply-To: <1272390345-3655-6-git-send-email-thellstrom@vmware.com>

From: Jakob Bornecrantz <jakob@vmware.com>

Signed-off-by: Jakob Bornecrantz <jakob@vmware.com>
Signed-off-by: Thomas Hellstrom <thellstrom@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  |   72 +++++++++++++-----------------
 drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c  |   70 ++++++++++++++++++++++++-----
 6 files changed, 148 insertions(+), 107 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 0c9c081..6241255 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 9a0a82b..1341ade 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -187,6 +187,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.
@@ -401,6 +402,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
@@ -491,6 +493,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 a933670..897ece5 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
@@ -132,16 +132,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;
 	}
@@ -154,8 +152,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);
@@ -164,18 +162,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);
@@ -183,13 +174,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;
 }
 
@@ -416,48 +416,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 a8e5445..e6a1eb7 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 146792e..9d0defa 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;
@@ -833,24 +813,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);
@@ -859,6 +840,12 @@ 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;
 }
@@ -873,9 +860,12 @@ 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 06618a3..1b818c1 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;
 }
 
@@ -491,18 +531,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.2.5

  reply	other threads:[~2010-04-27 17:46 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-04-27 17:45 [PATCH 0/13] vmwgfx update Thomas Hellstrom
2010-04-27 17:45 ` [PATCH 01/13] drm/vmwgfx: Assume larger framebuffer max size Thomas Hellstrom
2010-04-27 17:45   ` [PATCH 02/13] drm/vmwgfx: Fix single framebuffer detection Thomas Hellstrom
2010-04-27 17:45     ` [PATCH 03/13] drm/vmwgfx: Make sure to unpin old and pin new framebuffer Thomas Hellstrom
2010-04-27 17:45       ` [PATCH 04/13] drm/vmwgfx: Add kernel throttling support. Bump minor Thomas Hellstrom
2010-04-27 17:45         ` [PATCH 05/13] drm/vmwgfx: Get connector status from detection function Thomas Hellstrom
2010-04-27 17:45           ` Thomas Hellstrom [this message]
2010-04-27 17:45             ` [PATCH 07/13] drm/vmwgfx: Reserve first part of VRAM for framebuffer Thomas Hellstrom
2010-04-27 17:45               ` [PATCH 08/13] drm/vmwgfx: Remove duplicate member from struct vmw_legacy_display_unit Thomas Hellstrom
2010-04-27 17:45                 ` [PATCH 09/13] drm/vmwgfx: Don't use SVGA_REG_ENABLE in modesetting code Thomas Hellstrom
2010-04-27 17:45                   ` [PATCH 10/13] drm/vmwgfx: Some modesetting cleanups and fixes Thomas Hellstrom
2010-04-27 17:45                     ` [PATCH 11/13] drm/vmwgfx: Unpause overlay on update Thomas Hellstrom
2010-04-27 17:45                       ` [PATCH 12/13] drm/vmwgfx: Print warnings in kernel log about bo pinning that fails Thomas Hellstrom
2010-04-27 17:45                         ` [PATCH 13/13] drm/vmwgfx: Remove some leftover debug messages Thomas Hellstrom
2010-04-28  8:49     ` [PATCH 02/13] drm/vmwgfx: Fix single framebuffer detection Paulius Zaleckas
  -- strict thread matches above, loose matches on Subject: below --
2010-05-28  9:21 [PATCH 0/13] vmwgfx update V2 Thomas Hellstrom
2010-05-28  9:21 ` [PATCH 01/13] drm/vmwgfx: Assume larger framebuffer max size Thomas Hellstrom
2010-05-28  9:21   ` [PATCH 02/13] drm/vmwgfx: Fix single framebuffer detection Thomas Hellstrom
2010-05-28  9:21     ` [PATCH 03/13] drm/vmwgfx: Make sure to unpin old and pin new framebuffer Thomas Hellstrom
2010-05-28  9:21       ` [PATCH 04/13] drm/vmwgfx: Add kernel throttling support. Bump minor Thomas Hellstrom
2010-05-28  9:21         ` [PATCH 05/13] drm/vmwgfx: Get connector status from detection function Thomas Hellstrom
2010-05-28  9:21           ` [PATCH 06/13] drm/vmwgfx: Support older hardware Thomas Hellstrom

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1272390345-3655-7-git-send-email-thellstrom@vmware.com \
    --to=thellstrom@vmware.com \
    --cc=airlied@gmail.com \
    --cc=dri-devel@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.