Uses VRAM as the scanout buffer then switches the device to legacy mode.
Restrict support to 64 Bit so we don't waste valuable VA space on the
mostly unused VRAM mapping.

Suggested-by: Ryosuke Yasuoka <[email protected]>
Signed-off-by: Ian Forbes <[email protected]>
---

v2:
 - Set SVGA_REG_CONFIG_DONE=false so that SVGA3 works correctly
v3:
 - Rebase
 - Pre-map VRAM
 - Restrict to 64 Bit only

 drivers/gpu/drm/vmwgfx/vmwgfx_drv.c  |  6 +++++
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.h  |  1 +
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c  | 34 ++++++++++++++++++++++++++++
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.h  |  5 ++++
 drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c |  4 ++++
 5 files changed, 50 insertions(+)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 0f101aedb49a..e6e38b7a2d5b 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -761,6 +761,12 @@ static int vmw_setup_pci_resources(struct vmw_private *dev,
                return -EINVAL;
        }
 
+#if defined(CONFIG_64BIT)
+       dev->vram_mem = devm_memremap(dev->drm.dev,
+                                     dev->vram_start,
+                                     dev->vram_size,
+                                     MEMREMAP_WB | MEMREMAP_DEC);
+#endif
        /*
         * This is approximate size of the vram, the exact size will only
         * be known after we read SVGA_REG_VRAM_SIZE. The PCI resource
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h 
b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 38bea8abab84..463b5a5dfc43 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -472,6 +472,7 @@ struct vmw_private {
        resource_size_t max_primary_mem;
        u32 __iomem *rmmio;
        u32 *fifo_mem;
+       u32 *vram_mem;
        resource_size_t fifo_mem_size;
        uint32_t fb_max_width;
        uint32_t fb_max_height;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 31d3ee0825ca..2d5e51ed5568 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -21,6 +21,7 @@
 #include <drm/drm_sysfs.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_blend.h>
+#include <drm/drm_panic.h>
 
 void vmw_du_init(struct vmw_display_unit *du)
 {
@@ -2034,3 +2035,36 @@ bool vmw_user_object_is_null(struct vmw_user_object *uo)
 {
        return !uo->buffer && !uo->surface;
 }
+
+int
+vmw_get_scanout_buffer(struct drm_plane *plane, struct drm_scanout_buffer *sb)
+{
+       void  *vram;
+       struct vmw_private *vmw_priv = container_of(plane->dev, struct 
vmw_private, drm);
+
+       // Only call on the primary display
+       if (container_of(plane, struct vmw_display_unit, primary)->unit != 0)
+               return -EINVAL;
+
+       vram = vmw_priv->vram_mem;
+       if (!vram)
+               return -ENOMEM;
+
+       vmw_write(vmw_priv, SVGA_REG_CONFIG_DONE, false);
+
+       iosys_map_set_vaddr(&sb->map[0], vram);
+       sb->format = drm_format_info(DRM_FORMAT_RGB565);
+       sb->width  = vmw_priv->initial_width;
+       sb->height = vmw_priv->initial_height;
+       sb->pitch[0] = drm_format_info_min_pitch(sb->format, 0, sb->width);
+       return 0;
+}
+
+void vmw_panic_flush(struct drm_plane *plane)
+{
+       struct vmw_private *vmw_priv = container_of(plane->dev, struct 
vmw_private, drm);
+
+       vmw_kms_write_svga(vmw_priv,
+                          vmw_priv->initial_width, vmw_priv->initial_height,
+                          vmw_priv->initial_width * 2, 16, 16);
+}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h 
b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
index 2224d7d91d1b..139c194ec54b 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
@@ -498,6 +498,11 @@ int vmw_kms_stdu_readback(struct vmw_private *dev_priv,
 
 int vmw_du_helper_plane_update(struct vmw_du_update_plane *update);
 
+struct drm_scanout_buffer;
+
+int vmw_get_scanout_buffer(struct drm_plane *pl, struct drm_scanout_buffer 
*sb);
+void vmw_panic_flush(struct drm_plane *plane);
+
 /**
  * vmw_du_translate_to_crtc - Translate a rect from framebuffer to crtc
  * @state: Plane state.
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
index 4139837f4caf..bf4b22cd9e5d 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
@@ -1506,6 +1506,10 @@ drm_plane_helper_funcs 
vmw_stdu_primary_plane_helper_funcs = {
        .atomic_update = vmw_stdu_primary_plane_atomic_update,
        .prepare_fb = vmw_stdu_primary_plane_prepare_fb,
        .cleanup_fb = vmw_stdu_primary_plane_cleanup_fb,
+#if defined(CONFIG_64BIT)
+       .get_scanout_buffer = vmw_get_scanout_buffer,
+       .panic_flush = vmw_panic_flush,
+#endif
 };
 
 static const struct drm_crtc_helper_funcs vmw_stdu_crtc_helper_funcs = {
-- 
2.55.0

Reply via email to