From: Martin Krastev <krast...@vmware.com>

* Add support for CursorMob
* Add support for CursorBypass 4

Reviewed-by: Zack Rusin <za...@vmware.com>
Signed-off-by: Martin Krastev <krast...@vmware.com>
Signed-off-by: Zack Rusin <za...@vmware.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 45 +++++++++++++++-
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.h |  6 +++
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 79 +++++++++++++++++++++++++++--
 3 files changed, 125 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 086dc75e7b42..7d8cc2f6b04e 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0 OR MIT
 /**************************************************************************
  *
- * Copyright 2009-2016 VMware, Inc., Palo Alto, CA., USA
+ * Copyright 2009-2021 VMware, Inc., Palo Alto, CA., USA
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the
@@ -301,8 +301,12 @@ static void vmw_print_capabilities2(uint32_t capabilities2)
                DRM_INFO("  Grow oTable.\n");
        if (capabilities2 & SVGA_CAP2_INTRA_SURFACE_COPY)
                DRM_INFO("  IntraSurface copy.\n");
+       if (capabilities2 & SVGA_CAP2_CURSOR_MOB)
+               DRM_INFO("  Cursor Mob.\n");
        if (capabilities2 & SVGA_CAP2_DX3)
                DRM_INFO("  DX3.\n");
+       if (capabilities2 & SVGA_CAP2_EXTRA_REGS)
+               DRM_INFO("  Extra Regs.\n");
 }
 
 static void vmw_print_capabilities(uint32_t capabilities)
@@ -505,6 +509,7 @@ static int vmw_request_device_late(struct vmw_private 
*dev_priv)
 static int vmw_request_device(struct vmw_private *dev_priv)
 {
        int ret;
+       size_t i;
 
        ret = vmw_device_init(dev_priv);
        if (unlikely(ret != 0)) {
@@ -526,6 +531,37 @@ static int vmw_request_device(struct vmw_private *dev_priv)
        if (unlikely(ret != 0))
                goto out_no_query_bo;
 
+       /* Set up mobs for cursor updates */
+       if (dev_priv->has_mob && dev_priv->capabilities2 & 
SVGA_CAP2_CURSOR_MOB) {
+               const uint32_t cursor_max_dim = vmw_read(dev_priv, 
SVGA_REG_CURSOR_MAX_DIMENSION);
+
+               for (i = 0; i < ARRAY_SIZE(dev_priv->cursor_mob); i++) {
+                       struct ttm_buffer_object **const bo = 
&dev_priv->cursor_mob[i];
+
+                       ret = vmw_bo_create_kernel(dev_priv,
+                               cursor_max_dim * cursor_max_dim * sizeof(u32) + 
sizeof(SVGAGBCursorHeader),
+                               &vmw_mob_placement, bo);
+
+                       if (ret != 0) {
+                               DRM_ERROR("Unable to create CursorMob 
array.\n");
+                               break;
+                       }
+
+                       BUG_ON((*bo)->resource->mem_type != VMW_PL_MOB);
+
+                       /* Fence the mob creation so we are guarateed to have 
the mob */
+                       ret = ttm_bo_reserve(*bo, false, true, NULL);
+                       BUG_ON(ret);
+
+                       vmw_bo_fence_single(*bo, NULL);
+
+                       ttm_bo_unreserve(*bo);
+
+                       DRM_INFO("Using CursorMob mobid %lu, max dimension 
%u\n",
+                                (*bo)->resource->start, cursor_max_dim);
+               }
+       }
+
        return 0;
 
 out_no_query_bo:
@@ -556,6 +592,8 @@ static int vmw_request_device(struct vmw_private *dev_priv)
  */
 static void vmw_release_device_early(struct vmw_private *dev_priv)
 {
+       size_t i;
+
        /*
         * Previous destructions should've released
         * the pinned bo.
@@ -570,6 +608,11 @@ static void vmw_release_device_early(struct vmw_private 
*dev_priv)
        if (dev_priv->has_mob) {
                struct ttm_resource_manager *man;
 
+               for (i = 0; i < ARRAY_SIZE(dev_priv->cursor_mob); i++) {
+                       if (dev_priv->cursor_mob[i] != NULL)
+                               ttm_bo_put(dev_priv->cursor_mob[i]);
+               }
+
                man = ttm_manager_type(&dev_priv->bdev, VMW_PL_MOB);
                ttm_resource_manager_evict_all(&dev_priv->bdev, man);
                vmw_otables_takedown(dev_priv);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h 
b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 356f82c26f59..46bf54f6169a 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -642,6 +642,12 @@ struct vmw_private {
        u8 mksstat_kern_top_timer[MKSSTAT_CAPACITY];
        atomic_t mksstat_kern_pids[MKSSTAT_CAPACITY];
 #endif
+
+       /*
+        * CursorMob buffer objects
+        */
+       struct ttm_buffer_object *cursor_mob[2];
+       atomic_t cursor_mob_idx;
 };
 
 static inline struct vmw_surface *vmw_res_to_srf(struct vmw_resource *res)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 2ddf4932d62c..8d7844354774 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0 OR MIT
 /**************************************************************************
  *
- * Copyright 2009-2015 VMware, Inc., Palo Alto, CA., USA
+ * Copyright 2009-2021 VMware, Inc., Palo Alto, CA., USA
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the
@@ -53,6 +53,10 @@ void vmw_du_cleanup(struct vmw_display_unit *du)
  * Display Unit Cursor functions
  */
 
+static int vmw_cursor_update_mob(struct vmw_private *dev_priv,
+                                u32 *image, u32 width, u32 height,
+                                u32 hotspotX, u32 hotspotY);
+
 static int vmw_cursor_update_image(struct vmw_private *dev_priv,
                                   u32 *image, u32 width, u32 height,
                                   u32 hotspotX, u32 hotspotY)
@@ -67,6 +71,10 @@ static int vmw_cursor_update_image(struct vmw_private 
*dev_priv,
        if (!image)
                return -EINVAL;
 
+       if (dev_priv->cursor_mob[ARRAY_SIZE(dev_priv->cursor_mob) - 1] != NULL)
+               return vmw_cursor_update_mob(dev_priv, image, width, height,
+                                            hotspotX, hotspotY);
+
        cmd = VMW_CMD_RESERVE(dev_priv, cmd_size);
        if (unlikely(cmd == NULL))
                return -ENOMEM;
@@ -87,6 +95,62 @@ static int vmw_cursor_update_image(struct vmw_private 
*dev_priv,
        return 0;
 }
 
+static int vmw_cursor_update_mob(struct vmw_private *dev_priv,
+                                u32 *image, u32 width, u32 height,
+                                u32 hotspotX, u32 hotspotY)
+{
+       SVGAGBCursorHeader *header;
+       SVGAGBAlphaCursorHeader *alpha_header;
+       const u32 image_size = width * height * sizeof(*image);
+       const u32 mob_size = sizeof(*header) + image_size;
+
+       struct ttm_buffer_object *bo;
+       struct ttm_bo_kmap_obj map;
+       bool dummy;
+       int ret;
+
+       bo = dev_priv->cursor_mob[atomic_inc_return(&dev_priv->cursor_mob_idx) %
+               ARRAY_SIZE(dev_priv->cursor_mob)];
+       BUG_ON(bo == NULL);
+
+       ret = ttm_bo_reserve(bo, true, false, NULL);
+
+       if (unlikely(ret != 0)) {
+               DRM_ERROR("reserve failed\n");
+               return -EINVAL;
+       }
+
+       ret = ttm_bo_kmap(bo, 0, vmw_num_pages(mob_size), &map);
+
+       if (unlikely(ret != 0))
+               goto err_map;
+
+       header = (SVGAGBCursorHeader *)ttm_kmap_obj_virtual(&map, &dummy);
+       alpha_header = &header->header.alphaHeader;
+
+       header->type = SVGA_ALPHA_CURSOR;
+       header->sizeInBytes = image_size;
+
+       alpha_header->hotspotX = hotspotX;
+       alpha_header->hotspotY = hotspotY;
+       alpha_header->width = width;
+       alpha_header->height = height;
+
+       memcpy(header + 1, image, image_size);
+
+       ttm_bo_kunmap(&map);
+       ttm_bo_unreserve(bo);
+
+       vmw_write(dev_priv, SVGA_REG_CURSOR_MOBID, bo->resource->start);
+
+       return 0;
+
+err_map:
+       ttm_bo_unreserve(bo);
+
+       return ret;
+}
+
 static int vmw_cursor_update_bo(struct vmw_private *dev_priv,
                                struct vmw_buffer_object *bo,
                                u32 width, u32 height,
@@ -127,11 +191,18 @@ static int vmw_cursor_update_bo(struct vmw_private 
*dev_priv,
 static void vmw_cursor_update_position(struct vmw_private *dev_priv,
                                       bool show, int x, int y)
 {
+       const uint32_t svga_cursor_on = show ? SVGA_CURSOR_ON_SHOW
+                                            : SVGA_CURSOR_ON_HIDE;
        uint32_t count;
 
        spin_lock(&dev_priv->cursor_lock);
-       if (vmw_is_cursor_bypass3_enabled(dev_priv)) {
-               vmw_fifo_mem_write(dev_priv, SVGA_FIFO_CURSOR_ON, show ? 1 : 0);
+       if (dev_priv->capabilities2 & SVGA_CAP2_EXTRA_REGS) {
+               vmw_write(dev_priv, SVGA_REG_CURSOR4_X, x);
+               vmw_write(dev_priv, SVGA_REG_CURSOR4_Y, y);
+               vmw_write(dev_priv, SVGA_REG_CURSOR4_ON, svga_cursor_on);
+               vmw_write(dev_priv, SVGA_REG_CURSOR4_SUBMIT, TRUE);
+       } else if (vmw_is_cursor_bypass3_enabled(dev_priv)) {
+               vmw_fifo_mem_write(dev_priv, SVGA_FIFO_CURSOR_ON, 
svga_cursor_on);
                vmw_fifo_mem_write(dev_priv, SVGA_FIFO_CURSOR_X, x);
                vmw_fifo_mem_write(dev_priv, SVGA_FIFO_CURSOR_Y, y);
                count = vmw_fifo_mem_read(dev_priv, SVGA_FIFO_CURSOR_COUNT);
@@ -139,7 +210,7 @@ static void vmw_cursor_update_position(struct vmw_private 
*dev_priv,
        } else {
                vmw_write(dev_priv, SVGA_REG_CURSOR_X, x);
                vmw_write(dev_priv, SVGA_REG_CURSOR_Y, y);
-               vmw_write(dev_priv, SVGA_REG_CURSOR_ON, show ? 1 : 0);
+               vmw_write(dev_priv, SVGA_REG_CURSOR_ON, svga_cursor_on);
        }
        spin_unlock(&dev_priv->cursor_lock);
 }
-- 
2.30.2

Reply via email to