Skip to contentSkip to conversation

drm/vmwgfx: Fixes and more support for old hardware

PATCH NAK Jakob Bornecrantz 1 participant 6 messages Jan 30, 2010 – Feb 2, 2010

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

cover drm/vmwgfx: Fixes and more support for old hardware

This a slightly updated patch series to the ones already sent out earlier. Not much to say about them except that I would like to get some more eyes or maybe even at tested-by on the last patch. Its quite intrusive. I wanted it to go out early so more people had access to it, release early and often and all that.

Peter patch 0004 should fix the problems you where having with getting kms working on VMware Workstation 5.5.2. It would be awesome if you could test it and give me a tested by on it.

Cheers Jakob.

------------------------------------------------------------------------------
The Planet: dedicated and managed hosting, cloud storage, colocation Stay online with enterprise data centers and the best network in the business Choose flexible plans and management services without long-term contracts Personal 24x7 support from experience hosting pros just a phone call away.
http://p.sf.net/sfu/theplanet-com
--

#1 lore raw

PATCH 1/4 drm/vmwgfx: Correctly detect 3D

---
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.c   |    2 ++
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.h   |    1 +
 drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c  |   19 +++++++++++++++++++
 drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c |    2 +-
 4 files changed, 23 insertions(+), 1 deletions(-)
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +2 -0
index dedd121..f47ff2c 100644
@@ -357,6 +357,8 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
 	dev_priv->pm_nb.notifier_call = vmwgfx_pm_notifier;
 	register_pm_notifier(&dev_priv->pm_nb);
 
+	DRM_INFO("%s", vmw_fifo_have_3d(dev_priv) ? "Have 3D\n" : "No 3D\n");
+
 	return 0;
 
 out_no_device:
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +1 -0
index 50529a7..59acc51 100644
@@ -389,6 +389,7 @@ extern int vmw_fifo_send_fence(struct vmw_private *dev_priv,
 			       uint32_t *sequence);
 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);
 
 /**
  * TTM glue - vmwgfx_ttm_glue.c
drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c +19 -0
index f7d5f70..4157547 100644
@@ -29,6 +29,25 @@
 #include "drmP.h"
 #include "ttm/ttm_placement.h"
 
+bool vmw_fifo_have_3d(struct vmw_private *dev_priv)
+{
+	__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
+	uint32_t fifo_min, hwversion;
+
+	fifo_min = ioread32(fifo_mem  + SVGA_FIFO_MIN);
+	if (fifo_min <= SVGA_FIFO_3D_HWVERSION * sizeof(unsigned int))
+		return false;
+
+	hwversion = ioread32(fifo_mem + SVGA_FIFO_3D_HWVERSION);
+	if (hwversion == 0)
+		return false;
+
+	if (hwversion < SVGA3D_HWVERSION_WS65_B1)
+		return false;
+
+	return true;
+}
+
 int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
 {
 	__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c +1 -1
index 5fa6a4e..778851f 100644
@@ -43,7 +43,7 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data,
 		param->value = vmw_overlay_num_free_overlays(dev_priv);
 		break;
 	case DRM_VMW_PARAM_3D:
-		param->value = dev_priv->capabilities & SVGA_CAP_3D ? 1 : 0;
+		param->value = vmw_fifo_have_3d(dev_priv) ? 1 : 0;
 		break;
 	case DRM_VMW_PARAM_FIFO_OFFSET:
 		param->value = dev_priv->mmio_start;
Signature · 10 lines
1.6.0.4


------------------------------------------------------------------------------
The Planet: dedicated and managed hosting, cloud storage, colocation
Stay online with enterprise data centers and the best network in the business
Choose flexible plans and management services without long-term contracts
Personal 24x7 support from experience hosting pros just a phone call away.
http://p.sf.net/sfu/theplanet-com
--
#2 lore raw

PATCH 2/4 drm/vmwgfx: Request SVGA version 2 and bail if not found

From: Peter Hanzel <[email protected]>

This fixes the driver not loading on older versions of VMware.

---
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.c |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +11 -0
index f47ff2c..a6e8f68 100644
@@ -209,6 +209,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
 {
 	struct vmw_private *dev_priv;
 	int ret;
+	uint32_t svga_id;
 
 	dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
 	if (unlikely(dev_priv == NULL)) {
@@ -239,6 +240,16 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
 	dev_priv->mmio_start = pci_resource_start(dev->pdev, 2);
 
 	mutex_lock(&dev_priv->hw_mutex);
+
+	vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2);
+	svga_id = vmw_read(dev_priv, SVGA_REG_ID);
+	if (svga_id != SVGA_ID_2) {
+		ret = -ENOSYS;
+		DRM_ERROR("Unsuported SVGA ID 0x%x\n", svga_id);
+		mutex_unlock(&dev_priv->hw_mutex);
+		goto out_err0;
+	}
+
 	dev_priv->capabilities = vmw_read(dev_priv, SVGA_REG_CAPABILITIES);
 
 	if (dev_priv->capabilities & SVGA_CAP_GMR) {
Signature · 10 lines
1.6.0.4


------------------------------------------------------------------------------
The Planet: dedicated and managed hosting, cloud storage, colocation
Stay online with enterprise data centers and the best network in the business
Choose flexible plans and management services without long-term contracts
Personal 24x7 support from experience hosting pros just a phone call away.
http://p.sf.net/sfu/theplanet-com
--
#3 lore raw

PATCH 3/4 drm/vmwgfx: Don't send bad flags to the host

---
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.h      |    2 ++
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c      |   10 ++++++++++
 drivers/gpu/drm/vmwgfx/vmwgfx_resource.c |   16 +++++++++++++++-
 3 files changed, 27 insertions(+), 1 deletions(-)
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +2 -0
index 59acc51..135be96 100644
@@ -96,6 +96,8 @@ struct vmw_surface {
 	struct drm_vmw_size *sizes;
 	uint32_t num_sizes;
 
+	bool scanout;
+
 	/* TODO so far just a extra pointer */
 	struct vmw_cursor_snooper snooper;
 };
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +10 -0
index 686692d..eeba6d1 100644
@@ -707,6 +707,9 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
 	if (ret)
 		goto try_dmabuf;
 
+	if (!surface->scanout)
+		goto err_not_scanout;
+
 	ret = vmw_kms_new_framebuffer_surface(dev_priv, surface, &vfb,
 					      mode_cmd->width, mode_cmd->height);
 
@@ -740,6 +743,13 @@ try_dmabuf:
 	}
 
 	return &vfb->base;
+
+err_not_scanout:
+	DRM_ERROR("surface not marked as scanout\n");
+	/* vmw_user_surface_lookup takes one ref */
+	vmw_surface_unreference(&surface);
+
+	return NULL;
 }
 
 static int vmw_kms_fb_changed(struct drm_device *dev)
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +15 -1
index e01db12..c7efbd4 100644
@@ -35,6 +35,11 @@
 #define VMW_RES_SURFACE ttm_driver_type1
 #define VMW_RES_STREAM ttm_driver_type2
 
+/* XXX: This isn't a real hardware flag, but just a hack for kernel to
+ * know about primary surfaces. Find a better way to accomplish this.
+ */
+#define SVGA3D_SURFACE_HINT_SCANOUT (1 << 9)
+
 struct vmw_user_context {
 	struct ttm_base_object base;
 	struct vmw_resource res;
@@ -599,8 +604,17 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
 	if (unlikely(ret != 0))
 		goto out_err1;
 
+	if (srf->flags & SVGA3D_SURFACE_HINT_SCANOUT) {
+		/* we should not send this flag down to hardware since
+		 * its not a official one
+		 */
+		srf->flags &= ~SVGA3D_SURFACE_HINT_SCANOUT;
+		srf->scanout = true;
+	} else {
+		srf->scanout = false;
+	}
 
-	if (srf->flags & (1 << 9) &&
+	if (srf->scanout &&
 	    srf->num_sizes == 1 &&
 	    srf->sizes[0].width == 64 &&
 	    srf->sizes[0].height == 64 &&
Signature · 10 lines
1.6.0.4


------------------------------------------------------------------------------
The Planet: dedicated and managed hosting, cloud storage, colocation
Stay online with enterprise data centers and the best network in the business
Choose flexible plans and management services without long-term contracts
Personal 24x7 support from experience hosting pros just a phone call away.
http://p.sf.net/sfu/theplanet-com
--
#4 lore raw

PATCH 4/4 drm/vmwgfx: Handle old hardware

This allows both fbdev and kms to work on older hardware that does not have the display topology cap.

There are also some other misc improvments related to handling older hardware version of SVGA. The current cut of is if the pitchlock cap is not set.

---
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.c  |    9 +++++
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.h  |    2 +
 drivers/gpu/drm/vmwgfx/vmwgfx_fb.c   |   45 +++++++++++++----------
 drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c |   18 +++++++++
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c  |   25 +++++++------
 drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c  |   64 +++++++++++++++++++++++++++-------
 6 files changed, 119 insertions(+), 44 deletions(-)
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +9 -0
index a6e8f68..5268af2 100644
@@ -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);
 
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +2 -0
index 135be96..3e03cb7 100644
@@ -178,6 +178,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.
@@ -392,6 +393,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
drivers/gpu/drm/vmwgfx/vmwgfx_fb.c +25 -20

82 lines not on this page · raw message

drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c +18 -0
index 4157547..c9560a0 100644
@@ -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;
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +14 -11
index eeba6d1..ab8cf4e 100644
@@ -596,12 +596,12 @@ 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);
+	if (dev_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) {
 		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);
@@ -610,7 +610,6 @@ static int vmw_framebuffer_dmabuf_pin(struct vmw_framebuffer *vfb)
 		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);
@@ -618,8 +617,8 @@ static int vmw_framebuffer_dmabuf_pin(struct vmw_framebuffer *vfb)
 		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_write(dev_priv, SVGA_REG_ENABLE, 1);
+	} /* ldu code takes care of !DISPLAY_TOPOLOGY case */
 
 	vmw_overlay_resume_all(dev_priv);
 
@@ -668,7 +667,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;
@@ -839,8 +838,7 @@ int vmw_kms_save_vga(struct vmw_private *vmw_priv)
 	 * 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);
+	if (vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) {
 		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);
@@ -858,6 +856,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_fifo_have_pitchlock(vmw_priv))
+		vmw_priv->vga_pitchlock = ioread32(vmw_priv->mmio_virt + SVGA_FIFO_PITCHLOCK);
+	else if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK)
+		vmw_priv->vga_pitchlock = vmw_read(vmw_priv, SVGA_REG_PITCHLOCK);
 
 	return 0;
 }
@@ -872,9 +874,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_fifo_have_pitchlock(vmw_priv))
+		iowrite32(vmw_priv->vga_pitchlock, vmw_priv->mmio_virt + SVGA_FIFO_PITCHLOCK);
+	else if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK)
+		vmw_write(vmw_priv, SVGA_REG_PITCHLOCK, vmw_priv->vga_pitchlock);
 
 	return 0;
 }
drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +51 -13

101 lines not on this page · raw message

Signature · 10 lines
1.6.0.4


------------------------------------------------------------------------------
The Planet: dedicated and managed hosting, cloud storage, colocation
Stay online with enterprise data centers and the best network in the business
Choose flexible plans and management services without long-term contracts
Personal 24x7 support from experience hosting pros just a phone call away.
http://p.sf.net/sfu/theplanet-com
--
#5 lore raw

Re: [PATCH 4/4] drm/vmwgfx: Handle old hardware

Quoted 8 lines · Jakob Bornecrantz

This allows both fbdev and kms to work on older hardware that does not have the display topology cap.

There are also some other misc improvments related to handling older hardware version of SVGA. The current cut of is if the pitchlock cap is not set.

NACK: Turns out that this patch has problems reboots and fails to set a mode.

I'm working on something more proper.

Cheers Jakob.

------------------------------------------------------------------------------
The Planet: dedicated and managed hosting, cloud storage, colocation Stay online with enterprise data centers and the best network in the business Choose flexible plans and management services without long-term contracts Personal 24x7 support from experience hosting pros just a phone call away.
http://p.sf.net/sfu/theplanet-com
--