config DRM_MGAG200
        tristate "Kernel modesetting driver for MGA G200 server engines"
        depends on DRM && PCI && MMU
+       select DRM_GEM_SHMEM_HELPER
        select DRM_KMS_HELPER
-       select DRM_VRAM_HELPER
-       select DRM_TTM
-       select DRM_TTM_HELPER
        help
         This is a KMS driver for the MGA G200 server chips, it
         does not support the original MGA G200 or any of the desktop
 
  * which then performs further device association and calls our graphics init
  * functions
  */
-int mgag200_modeset = -1;
 
+int mgag200_modeset = -1;
 MODULE_PARM_DESC(modeset, "Disable/Enable modesetting");
 module_param_named(modeset, mgag200_modeset, int, 0400);
 
-int mgag200_hw_bug_no_startadd = -1;
-MODULE_PARM_DESC(modeset, "HW does not interpret scanout-buffer start address correctly");
-module_param_named(hw_bug_no_startadd, mgag200_hw_bug_no_startadd, int, 0400);
-
 static struct drm_driver driver;
 
 static const struct pci_device_id pciidlist[] = {
 
 DEFINE_DRM_GEM_FOPS(mgag200_driver_fops);
 
-static bool mgag200_pin_bo_at_0(const struct mga_device *mdev)
-{
-       if (mgag200_hw_bug_no_startadd > 0) {
-               DRM_WARN_ONCE("Option hw_bug_no_startradd is enabled. Please "
-                             "report the output of 'lspci -vvnn' to "
-                             "<dri-devel@lists.freedesktop.org> if this "
-                             "option is required to make mgag200 work "
-                             "correctly on your system.\n");
-               return true;
-       } else if (!mgag200_hw_bug_no_startadd) {
-               return false;
-       }
-       return mdev->flags & MGAG200_FLAG_HW_BUG_NO_STARTADD;
-}
-
-int mgag200_driver_dumb_create(struct drm_file *file,
-                              struct drm_device *dev,
-                              struct drm_mode_create_dumb *args)
-{
-       struct mga_device *mdev = to_mga_device(dev);
-       unsigned long pg_align;
-
-       if (WARN_ONCE(!dev->vram_mm, "VRAM MM not initialized"))
-               return -EINVAL;
-
-       pg_align = 0ul;
-
-       /*
-        * Aligning scanout buffers to the size of the video ram forces
-        * placement at offset 0. Works around a bug where HW does not
-        * respect 'startadd' field.
-        */
-       if (mgag200_pin_bo_at_0(mdev))
-               pg_align = PFN_UP(mdev->mc.vram_size);
-
-       return drm_gem_vram_fill_create_dumb(file, dev, pg_align, 0, args);
-}
-
 static struct drm_driver driver = {
        .driver_features = DRIVER_ATOMIC | DRIVER_GEM | DRIVER_MODESET,
        .fops = &mgag200_driver_fops,
        .major = DRIVER_MAJOR,
        .minor = DRIVER_MINOR,
        .patchlevel = DRIVER_PATCHLEVEL,
-       .debugfs_init = drm_vram_mm_debugfs_init,
-       .dumb_create = mgag200_driver_dumb_create,
-       .dumb_map_offset = drm_gem_vram_driver_dumb_mmap_offset,
-       .gem_prime_mmap = drm_gem_prime_mmap,
+       DRM_GEM_SHMEM_DRIVER_OPS,
 };
 
 static struct pci_driver mgag200_pci_driver = {
 
 #include <drm/drm_encoder.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem.h>
-#include <drm/drm_gem_vram_helper.h>
+#include <drm/drm_gem_shmem_helper.h>
 #include <drm/drm_simple_kms_helper.h>
 
 #include "mgag200_reg.h"
 
        struct mga_mc                   mc;
 
-       size_t vram_fb_available;
+       void __iomem                    *vram;
+       size_t                          vram_fb_available;
 
        enum mga_type                   type;
        int                             has_sdram;
 
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_atomic_state_helper.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_damage_helper.h>
+#include <drm/drm_format_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_plane_helper.h>
        return MODE_OK;
 }
 
+static void
+mgag200_handle_damage(struct mga_device *mdev, struct drm_framebuffer *fb,
+                     struct drm_rect *clip)
+{
+       struct drm_device *dev = mdev->dev;
+       void *vmap;
+
+       vmap = drm_gem_shmem_vmap(fb->obj[0]);
+       if (drm_WARN_ON(dev, !vmap))
+               return; /* BUG: SHMEM BO should always be vmapped */
+
+       drm_fb_memcpy_dstclip(mdev->vram, vmap, fb, clip);
+
+       drm_gem_shmem_vunmap(fb->obj[0], vmap);
+
+       /* Always scanout image at VRAM offset 0 */
+       mgag200_set_startadd(mdev, (u32)0);
+       mgag200_set_offset(mdev, fb);
+}
+
 static void
 mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
                                   struct drm_crtc_state *crtc_state,
        struct mga_device *mdev = to_mga_device(dev);
        struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
        struct drm_framebuffer *fb = plane_state->fb;
-       struct drm_gem_vram_object *gbo;
-       s64 gpu_addr;
-
-       gbo = drm_gem_vram_of_gem(fb->obj[0]);
-
-       gpu_addr = drm_gem_vram_offset(gbo);
-       if (drm_WARN_ON_ONCE(dev, gpu_addr < 0))
-               return; /* BUG: BO should have been pinned to VRAM. */
+       struct drm_rect fullscreen = {
+               .x1 = 0,
+               .x2 = fb->width,
+               .y1 = 0,
+               .y2 = fb->height,
+       };
 
        mga_crtc_prepare(crtc);
 
                mgag200_g200ev_set_hiprilvl(mdev);
 
        mga_crtc_commit(crtc);
+
+       mgag200_handle_damage(mdev, fb, &fullscreen);
 }
 
 static void
        struct mga_device *mdev = to_mga_device(dev);
        struct drm_plane_state *state = plane->state;
        struct drm_framebuffer *fb = state->fb;
-       struct drm_gem_vram_object *gbo;
-       s64 gpu_addr;
+       struct drm_rect damage;
 
        if (!fb)
                return;
 
-       gbo = drm_gem_vram_of_gem(fb->obj[0]);
-
-       gpu_addr = drm_gem_vram_offset(gbo);
-       if (drm_WARN_ON_ONCE(dev, gpu_addr < 0))
-               return; /* BUG: BO should have been pinned to VRAM. */
-
-       mgag200_set_startadd(mdev, (unsigned long)gpu_addr);
-       mgag200_set_offset(mdev, fb);
+       if (drm_atomic_helper_damage_merged(old_state, state, &damage))
+               mgag200_handle_damage(mdev, fb, &damage);
 }
 
 static const struct drm_simple_display_pipe_funcs
        .disable    = mgag200_simple_display_pipe_disable,
        .check      = mgag200_simple_display_pipe_check,
        .update     = mgag200_simple_display_pipe_update,
-       .prepare_fb = drm_gem_vram_simple_display_pipe_prepare_fb,
-       .cleanup_fb = drm_gem_vram_simple_display_pipe_cleanup_fb,
+       .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb,
 };
 
 static const uint32_t mgag200_simple_display_pipe_formats[] = {
  */
 
 static const struct drm_mode_config_funcs mgag200_mode_config_funcs = {
-       .fb_create     = drm_gem_fb_create,
-       .mode_valid    = drm_vram_helper_mode_valid,
+       .fb_create     = drm_gem_fb_create_with_dirty,
        .atomic_check  = drm_atomic_helper_check,
        .atomic_commit = drm_atomic_helper_commit,
 };
        dev->mode_config.max_height = MGAG200_MAX_FB_HEIGHT;
 
        dev->mode_config.preferred_depth = mgag200_preferred_depth(mdev);
-       dev->mode_config.prefer_shadow = 1;
 
        dev->mode_config.fb_base = mdev->mc.vram_base;
 
 
 
 int mgag200_mm_init(struct mga_device *mdev)
 {
-       struct drm_vram_mm *vmm;
-       int ret;
        struct drm_device *dev = mdev->dev;
-
-       vmm = drm_vram_helper_alloc_mm(dev, pci_resource_start(dev->pdev, 0),
-                                      mdev->mc.vram_size);
-       if (IS_ERR(vmm)) {
-               ret = PTR_ERR(vmm);
-               DRM_ERROR("Error initializing VRAM MM; %d\n", ret);
-               return ret;
-       }
+       int ret;
 
        arch_io_reserve_memtype_wc(pci_resource_start(dev->pdev, 0),
                                   pci_resource_len(dev->pdev, 0));
        mdev->fb_mtrr = arch_phys_wc_add(pci_resource_start(dev->pdev, 0),
                                         pci_resource_len(dev->pdev, 0));
 
+       mdev->vram = ioremap(pci_resource_start(dev->pdev, 0),
+                            pci_resource_len(dev->pdev, 0));
+       if (!mdev->vram) {
+               ret = -ENOMEM;
+               goto err_arch_phys_wc_del;
+       }
+
        mdev->vram_fb_available = mdev->mc.vram_size;
 
        return 0;
+
+err_arch_phys_wc_del:
+       arch_phys_wc_del(mdev->fb_mtrr);
+       arch_io_free_memtype_wc(pci_resource_start(dev->pdev, 0),
+                               pci_resource_len(dev->pdev, 0));
+       return ret;
 }
 
 void mgag200_mm_fini(struct mga_device *mdev)
        struct drm_device *dev = mdev->dev;
 
        mdev->vram_fb_available = 0;
-
-       drm_vram_helper_release_mm(dev);
-
+       iounmap(mdev->vram);
        arch_io_free_memtype_wc(pci_resource_start(dev->pdev, 0),
                                pci_resource_len(dev->pdev, 0));
        arch_phys_wc_del(mdev->fb_mtrr);