aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom@vmware.com>2011-08-31 03:42:52 -0400
committerDave Airlie <airlied@redhat.com>2011-09-01 04:38:00 -0400
commit05730b32a78dab4bed8fb7ccc64c53d9fcf31e9d (patch)
tree0c01aee6881e52d22c727284e18e2efd3dd31592 /drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
parentbe38ab6ea7b0de0542a0ff78690d63bb22f66a4d (diff)
vmwgfx: Switch to VGA when we drop master and vmwgfx fbdev is not active
Previously this was not done when any 3D resource was active, since that meant disabling the fifo with all 3D state lost. Now, if there are still 3D resources active, we use the svga hide feature. This fixes X server VT switching with 3D enabled. Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com> Reviewed-by: Jakob Bornecrantz <jakob@vmware.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_drv.c')
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.c54
1 files changed, 42 insertions, 12 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 62d54b940474..3d6a073e130b 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -209,7 +209,14 @@ static void vmw_release_device(struct vmw_private *dev_priv)
209 vmw_fifo_release(dev_priv, &dev_priv->fifo); 209 vmw_fifo_release(dev_priv, &dev_priv->fifo);
210} 210}
211 211
212int vmw_3d_resource_inc(struct vmw_private *dev_priv) 212/**
213 * Increase the 3d resource refcount.
214 * If the count was prevously zero, initialize the fifo, switching to svga
215 * mode. Note that the master holds a ref as well, and may request an
216 * explicit switch to svga mode if fb is not running, using @unhide_svga.
217 */
218int vmw_3d_resource_inc(struct vmw_private *dev_priv,
219 bool unhide_svga)
213{ 220{
214 int ret = 0; 221 int ret = 0;
215 222
@@ -218,19 +225,42 @@ int vmw_3d_resource_inc(struct vmw_private *dev_priv)
218 ret = vmw_request_device(dev_priv); 225 ret = vmw_request_device(dev_priv);
219 if (unlikely(ret != 0)) 226 if (unlikely(ret != 0))
220 --dev_priv->num_3d_resources; 227 --dev_priv->num_3d_resources;
228 } else if (unhide_svga) {
229 mutex_lock(&dev_priv->hw_mutex);
230 vmw_write(dev_priv, SVGA_REG_ENABLE,
231 vmw_read(dev_priv, SVGA_REG_ENABLE) &
232 ~SVGA_REG_ENABLE_HIDE);
233 mutex_unlock(&dev_priv->hw_mutex);
221 } 234 }
235
222 mutex_unlock(&dev_priv->release_mutex); 236 mutex_unlock(&dev_priv->release_mutex);
223 return ret; 237 return ret;
224} 238}
225 239
226 240/**
227void vmw_3d_resource_dec(struct vmw_private *dev_priv) 241 * Decrease the 3d resource refcount.
242 * If the count reaches zero, disable the fifo, switching to vga mode.
243 * Note that the master holds a refcount as well, and may request an
244 * explicit switch to vga mode when it releases its refcount to account
245 * for the situation of an X server vt switch to VGA with 3d resources
246 * active.
247 */
248void vmw_3d_resource_dec(struct vmw_private *dev_priv,
249 bool hide_svga)
228{ 250{
229 int32_t n3d; 251 int32_t n3d;
230 252
231 mutex_lock(&dev_priv->release_mutex); 253 mutex_lock(&dev_priv->release_mutex);
232 if (unlikely(--dev_priv->num_3d_resources == 0)) 254 if (unlikely(--dev_priv->num_3d_resources == 0))
233 vmw_release_device(dev_priv); 255 vmw_release_device(dev_priv);
256 else if (hide_svga) {
257 mutex_lock(&dev_priv->hw_mutex);
258 vmw_write(dev_priv, SVGA_REG_ENABLE,
259 vmw_read(dev_priv, SVGA_REG_ENABLE) |
260 SVGA_REG_ENABLE_HIDE);
261 mutex_unlock(&dev_priv->hw_mutex);
262 }
263
234 n3d = (int32_t) dev_priv->num_3d_resources; 264 n3d = (int32_t) dev_priv->num_3d_resources;
235 mutex_unlock(&dev_priv->release_mutex); 265 mutex_unlock(&dev_priv->release_mutex);
236 266
@@ -399,7 +429,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
399 goto out_no_kms; 429 goto out_no_kms;
400 vmw_overlay_init(dev_priv); 430 vmw_overlay_init(dev_priv);
401 if (dev_priv->enable_fb) { 431 if (dev_priv->enable_fb) {
402 ret = vmw_3d_resource_inc(dev_priv); 432 ret = vmw_3d_resource_inc(dev_priv, false);
403 if (unlikely(ret != 0)) 433 if (unlikely(ret != 0))
404 goto out_no_fifo; 434 goto out_no_fifo;
405 vmw_kms_save_vga(dev_priv); 435 vmw_kms_save_vga(dev_priv);
@@ -429,7 +459,7 @@ out_no_irq:
429 if (dev_priv->enable_fb) { 459 if (dev_priv->enable_fb) {
430 vmw_fb_close(dev_priv); 460 vmw_fb_close(dev_priv);
431 vmw_kms_restore_vga(dev_priv); 461 vmw_kms_restore_vga(dev_priv);
432 vmw_3d_resource_dec(dev_priv); 462 vmw_3d_resource_dec(dev_priv, false);
433 } 463 }
434out_no_fifo: 464out_no_fifo:
435 vmw_overlay_close(dev_priv); 465 vmw_overlay_close(dev_priv);
@@ -474,7 +504,7 @@ static int vmw_driver_unload(struct drm_device *dev)
474 if (dev_priv->enable_fb) { 504 if (dev_priv->enable_fb) {
475 vmw_fb_close(dev_priv); 505 vmw_fb_close(dev_priv);
476 vmw_kms_restore_vga(dev_priv); 506 vmw_kms_restore_vga(dev_priv);
477 vmw_3d_resource_dec(dev_priv); 507 vmw_3d_resource_dec(dev_priv, false);
478 } 508 }
479 vmw_kms_close(dev_priv); 509 vmw_kms_close(dev_priv);
480 vmw_overlay_close(dev_priv); 510 vmw_overlay_close(dev_priv);
@@ -648,7 +678,7 @@ static int vmw_master_set(struct drm_device *dev,
648 int ret = 0; 678 int ret = 0;
649 679
650 if (!dev_priv->enable_fb) { 680 if (!dev_priv->enable_fb) {
651 ret = vmw_3d_resource_inc(dev_priv); 681 ret = vmw_3d_resource_inc(dev_priv, true);
652 if (unlikely(ret != 0)) 682 if (unlikely(ret != 0))
653 return ret; 683 return ret;
654 vmw_kms_save_vga(dev_priv); 684 vmw_kms_save_vga(dev_priv);
@@ -690,7 +720,7 @@ out_no_active_lock:
690 vmw_write(dev_priv, SVGA_REG_TRACES, 1); 720 vmw_write(dev_priv, SVGA_REG_TRACES, 1);
691 mutex_unlock(&dev_priv->hw_mutex); 721 mutex_unlock(&dev_priv->hw_mutex);
692 vmw_kms_restore_vga(dev_priv); 722 vmw_kms_restore_vga(dev_priv);
693 vmw_3d_resource_dec(dev_priv); 723 vmw_3d_resource_dec(dev_priv, true);
694 } 724 }
695 return ret; 725 return ret;
696} 726}
@@ -728,7 +758,7 @@ static void vmw_master_drop(struct drm_device *dev,
728 vmw_write(dev_priv, SVGA_REG_TRACES, 1); 758 vmw_write(dev_priv, SVGA_REG_TRACES, 1);
729 mutex_unlock(&dev_priv->hw_mutex); 759 mutex_unlock(&dev_priv->hw_mutex);
730 vmw_kms_restore_vga(dev_priv); 760 vmw_kms_restore_vga(dev_priv);
731 vmw_3d_resource_dec(dev_priv); 761 vmw_3d_resource_dec(dev_priv, true);
732 } 762 }
733 763
734 dev_priv->active_master = &dev_priv->fbdev_master; 764 dev_priv->active_master = &dev_priv->fbdev_master;
@@ -837,7 +867,7 @@ static int vmw_pm_prepare(struct device *kdev)
837 */ 867 */
838 dev_priv->suspended = true; 868 dev_priv->suspended = true;
839 if (dev_priv->enable_fb) 869 if (dev_priv->enable_fb)
840 vmw_3d_resource_dec(dev_priv); 870 vmw_3d_resource_dec(dev_priv, true);
841 871
842 if (dev_priv->num_3d_resources != 0) { 872 if (dev_priv->num_3d_resources != 0) {
843 873
@@ -845,7 +875,7 @@ static int vmw_pm_prepare(struct device *kdev)
845 "while 3D resources are active.\n"); 875 "while 3D resources are active.\n");
846 876
847 if (dev_priv->enable_fb) 877 if (dev_priv->enable_fb)
848 vmw_3d_resource_inc(dev_priv); 878 vmw_3d_resource_inc(dev_priv, true);
849 dev_priv->suspended = false; 879 dev_priv->suspended = false;
850 return -EBUSY; 880 return -EBUSY;
851 } 881 }
@@ -864,7 +894,7 @@ static void vmw_pm_complete(struct device *kdev)
864 * start fifo. 894 * start fifo.
865 */ 895 */
866 if (dev_priv->enable_fb) 896 if (dev_priv->enable_fb)
867 vmw_3d_resource_inc(dev_priv); 897 vmw_3d_resource_inc(dev_priv, false);
868 898
869 dev_priv->suspended = false; 899 dev_priv->suspended = false;
870} 900}