drm/glint: add bare TTM memory manager and framebuffer

The TTM code uses the drm_addmap hack, so I can get something on the
screen sooner rather than later.

Signed-off-by: Matt Turner <mattst88@gmail.com>
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 87e33ea..8bafa45 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -131,6 +131,11 @@
 config DRM_GLINT
 	tristate "Permedia (GLint) 3/4 driver"
 	depends on DRM && AGP
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select DRM_KMS_HELPER
+	select DRM_TTM
 
 config DRM_MGA
 	tristate "Matrox g200/g400"
diff --git a/drivers/gpu/drm/glint/Makefile b/drivers/gpu/drm/glint/Makefile
index 27f4c94..f65d255 100644
--- a/drivers/gpu/drm/glint/Makefile
+++ b/drivers/gpu/drm/glint/Makefile
@@ -4,6 +4,7 @@
 
 ccflags-y := -Iinclude/drm
 glint-y   := glint_crtc.o glint_dac.o glint_device.o glint_display.o \
-	glint_drv.o glint_irq.o glint_kms.o glint_vga.o
+	glint_drv.o glint_fbdev.o glint_framebuffer.o \
+	glint_irq.o glint_kms.o glint_ttm.o glint_vga.o init_ttm.o
 
 obj-$(CONFIG_DRM_GLINT) += glint.o
diff --git a/drivers/gpu/drm/glint/glint.h b/drivers/gpu/drm/glint/glint.h
index 243043b..c4dc408 100644
--- a/drivers/gpu/drm/glint/glint.h
+++ b/drivers/gpu/drm/glint/glint.h
@@ -4,11 +4,22 @@
 #include "glint_family.h"
 #include "glint_mode.h"
 
+#include <ttm/ttm_bo_api.h>
+#include <ttm/ttm_bo_driver.h>
+#include <ttm/ttm_placement.h>
+#include <ttm/ttm_module.h>
+#include <ttm/ttm_page_alloc.h>
+
+#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
+struct glint_mman {
+	struct ttm_global_reference	mem_global_ref;
+	struct ttm_bo_global_ref	bo_global_ref;
+	struct ttm_bo_device		bdev;
+};
+
 struct glint_mc {
-	resource_size_t			aper_size;
-	resource_size_t			aper_base;
-	char __iomem			*vram;
-	u32				vram_size;
+	resource_size_t			vram_size;
+	resource_size_t			vram_base;
 };
 
 struct glint_device {
@@ -22,8 +33,11 @@
 	resource_size_t			rmmio_size;
 	void __iomem			*rmmio;
 
+	drm_local_map_t			*framebuffer;
+
 	struct glint_mc			mc;
 	struct glint_mode_info		mode_info;
+	struct glint_mman		mman;
 
 	int				num_crtc;
 };
diff --git a/drivers/gpu/drm/glint/glint_crtc.c b/drivers/gpu/drm/glint/glint_crtc.c
index 01f5a5f..ea60d37 100644
--- a/drivers/gpu/drm/glint/glint_crtc.c
+++ b/drivers/gpu/drm/glint/glint_crtc.c
@@ -167,3 +167,25 @@
 
 	drm_crtc_helper_add(&glint_crtc->base, &glint_helper_funcs);
 }
+
+/** Sets the color ramps on behalf of fbcon */
+void glint_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
+			     u16 blue, int regno)
+{
+	struct glint_crtc *glint_crtc = to_glint_crtc(crtc);
+
+	glint_crtc->lut_r[regno] = red;
+	glint_crtc->lut_g[regno] = green;
+	glint_crtc->lut_b[regno] = blue;
+}
+
+/** Gets the color ramps on behalf of fbcon */
+void glint_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
+			     u16 *blue, int regno)
+{
+	struct glint_crtc *glint_crtc = to_glint_crtc(crtc);
+
+	*red = glint_crtc->lut_r[regno];
+	*green = glint_crtc->lut_g[regno];
+	*blue = glint_crtc->lut_b[regno];
+}
diff --git a/drivers/gpu/drm/glint/glint_device.c b/drivers/gpu/drm/glint/glint_device.c
index de5a428..cb8ecc8 100644
--- a/drivers/gpu/drm/glint/glint_device.c
+++ b/drivers/gpu/drm/glint/glint_device.c
@@ -12,13 +12,26 @@
 	u32 temp1, temp2;
 	u32 memsize = 0;
 	unsigned i;
-	char __iomem *vram = gdev->mc.vram;
+	char __iomem *vram;
+
+	vram = ioremap(gdev->mc.vram_base, gdev->mc.vram_size);
+	if (!vram) {
+		GLINT_ERROR("Unable to ioremap %lu MB of VRAM. Retrying...\n", (unsigned long)gdev->mc.vram_size / MB);
+		gdev->mc.vram_size /= 2;
+		ioremap(gdev->mc.vram_base, gdev->mc.vram_size);
+		if (!vram) {
+			GLINT_ERROR("Unable to ioremap %lu MB of VRAM. Bailing out.\n", (unsigned long)gdev->mc.vram_size / MB);
+			return -1;
+		}
+		GLINT_INFO("ioremapped %lu MB of VRAM.\n", (unsigned long)gdev->mc.vram_size / MB);
+	}
+	GLINT_INFO("vram base: 0x%08X\n", (uint32_t)gdev->mc.vram_base);
 
 	WREG32(PM3MemBypassWriteMask, 0xffffffff);
 
 #define TEST_PATTERN 0x00345678
 	for (i = 0; i < 32; i++) {
-		iowrite32(i * TEST_PATTERN, gdev->mc.vram + (i * MB));
+		iowrite32(i * TEST_PATTERN, vram + (i * MB));
 		mb();
 		temp1 = ioread32(vram + (i * MB));
 
@@ -54,28 +67,52 @@
 
 	WREG32(PM3MemBypassWriteMask, tempBypass);
 
+	iounmap(vram);
+
 	return (memsize + 1) * MB;
 }
 
 static int glint_vram_init(struct glint_device *gdev)
 {
-	/* work out accessible VRAM */
-	gdev->mc.aper_base = pci_resource_start(gdev->ddev->pdev, 1);
-	gdev->mc.aper_size = pci_resource_len(gdev->ddev->pdev, 1);
+	unsigned size;
+	int ret;
 
-	gdev->mc.vram = ioremap(gdev->mc.aper_base, gdev->mc.aper_size);
-	if (!gdev->mc.vram) {
-		GLINT_ERROR("Unable to ioremap %lu MB of VRAM. Retrying...\n", (unsigned long)gdev->mc.aper_size / MB);
-		gdev->mc.aper_size /= 2;
-		ioremap(gdev->mc.aper_base, gdev->mc.aper_size);
-		if (!gdev->mc.vram) {
-			GLINT_ERROR("Unable to ioremap %lu MB of VRAM. Bailing out.\n", (unsigned long)gdev->mc.aper_size / MB);
-			return -1;
-		}
-		GLINT_INFO("ioremapped %lu MB of VRAM.\n", (unsigned long)gdev->mc.aper_size / MB);
-	}
+	/* work out accessible VRAM */
+	gdev->mc.vram_base = pci_resource_start(gdev->ddev->pdev, 1);
+	gdev->mc.vram_size = pci_resource_len(gdev->ddev->pdev, 1);
+
 	gdev->mc.vram_size = glint_vram_size(gdev);
 
+	if (!request_region(gdev->mc.vram_base, gdev->mc.vram_size, "glintfb_vram")) {
+		GLINT_ERROR("can't region_reserve VRAM\n");
+		return -ENXIO;
+	}
+
+	ret = generic_ttm_global_init(&gdev->mman);
+	if (ret) {
+		GLINT_ERROR("failed to set up ttm\n");
+		return -1;
+	}
+
+	ret = ttm_bo_device_init(&gdev->mman.bdev,
+				gdev->mman.bo_global_ref.ref.object,
+				&glint_bo_driver, DRM_FILE_PAGE_OFFSET,
+				false);
+	if (ret) {
+		GLINT_ERROR("failed to set up buffer object driver: %d\n", ret);
+		return -1;
+	}
+
+	size = size & (PAGE_MASK << 1);
+	ret = ttm_bo_init_mm(&gdev->mman.bdev, TTM_PL_VRAM, size >> PAGE_SHIFT);
+	if (ret) {
+		GLINT_ERROR("failed vram init: %d\n", ret);
+		return -1;
+	}
+
+	ret = drm_addmap(gdev->ddev, gdev->mc.vram_base, gdev->mc.vram_size,
+		_DRM_FRAME_BUFFER, _DRM_WRITE_COMBINING,
+		&gdev->framebuffer);
 	return 0;
 }
 
@@ -83,8 +120,10 @@
 {
 	iounmap(gdev->rmmio);
 	gdev->rmmio = NULL;
-	iounmap(gdev->mc.vram);
-	gdev->mc.vram = NULL;
+	if (gdev->framebuffer)
+		drm_rmmap(gdev->ddev, gdev->framebuffer);
+	if (gdev->mc.vram_base)
+		release_region(gdev->mc.vram_base, gdev->mc.vram_size);
 }
 
 int glint_device_init(struct glint_device *gdev,
@@ -98,7 +137,7 @@
 	gdev->ddev = ddev;
 	gdev->pdev = pdev;
 	gdev->flags = flags;
-	gdev->num_crtc = 2;
+	gdev->num_crtc = 1;
 
 	/* Registers mapping */
 	/* TODO: block userspace mapping of io register */
diff --git a/drivers/gpu/drm/glint/glint_display.c b/drivers/gpu/drm/glint/glint_display.c
index 50da039..db0dae6 100644
--- a/drivers/gpu/drm/glint/glint_display.c
+++ b/drivers/gpu/drm/glint/glint_display.c
@@ -9,6 +9,7 @@
 {
 	struct drm_encoder *encoder;
 	struct drm_connector *connector;
+	int ret;
 	int i;
 
 	drm_mode_config_init(gdev->ddev);
@@ -17,7 +18,7 @@
 	gdev->ddev->mode_config.max_width = GLINT_MAX_FB_WIDTH;
 	gdev->ddev->mode_config.max_height = GLINT_MAX_FB_HEIGHT;
 
-	gdev->ddev->mode_config.fb_base = gdev->mc.aper_base;
+	gdev->ddev->mode_config.fb_base = gdev->mc.vram_base;
 
 	/* allocate crtcs */
 	for (i = 0; i < gdev->num_crtc; i++) {
@@ -38,11 +39,19 @@
 
 	drm_mode_connector_attach_encoder(connector, encoder);
 
+	ret = glint_fbdev_init(gdev);
+	if (ret) {
+		GLINT_ERROR("glint_fbdev_init failed\n");
+		return ret;
+	}
+
 	return 0;
 }
 
 void glint_modeset_fini(struct glint_device *gdev)
 {
+	glint_fbdev_fini(gdev);
+
 	if (gdev->mode_info.mode_config_initialized) {
 		drm_mode_config_cleanup(gdev->ddev);
 		gdev->mode_info.mode_config_initialized = false;
diff --git a/drivers/gpu/drm/glint/glint_drv.h b/drivers/gpu/drm/glint/glint_drv.h
index c48518c..0b962c3 100644
--- a/drivers/gpu/drm/glint/glint_drv.h
+++ b/drivers/gpu/drm/glint/glint_drv.h
@@ -33,6 +33,10 @@
 #include "glint.h"
 
 				/* glint_crtc.c */
+void glint_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
+			     u16 blue, int regno);
+void glint_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
+			     u16 *blue, int regno);
 void glint_crtc_init(struct drm_device *dev, int index);
 
 				/* glint_dac.c */
@@ -49,6 +53,15 @@
 int glint_modeset_init(struct glint_device *gdev);
 void glint_modeset_fini(struct glint_device *gdev);
 
+				/* glint_fbdev.c */
+int glint_fbdev_init(struct glint_device *gdev);
+void glint_fbdev_fini(struct glint_device *gdev);
+
+				/* glint_framebuffer.c */
+int glint_framebuffer_init(struct drm_device *dev,
+			   struct glint_framebuffer *gfb,
+			   struct drm_mode_fb_cmd *mode_cmd);
+
 				/* glint_irq.c */
 void glint_driver_irq_preinstall(struct drm_device *dev);
 int glint_driver_irq_postinstall(struct drm_device *dev);
@@ -61,7 +74,14 @@
 extern struct drm_ioctl_desc glint_ioctls[];
 extern int glint_max_ioctl;
 
+				/* glint_ttm.c */
+extern struct ttm_bo_driver glint_bo_driver;
+
 				/* glint_vga.c */
 struct drm_connector *glint_vga_init(struct drm_device *dev);
 
+				/* init_ttm.c */
+void generic_ttm_global_release(struct glint_mman *ttm);
+int generic_ttm_global_init(struct glint_mman *ttm);
+
 #endif				/* __GLINT_DRV_H__ */
diff --git a/drivers/gpu/drm/glint/glint_fbdev.c b/drivers/gpu/drm/glint/glint_fbdev.c
new file mode 100644
index 0000000..faec453
--- /dev/null
+++ b/drivers/gpu/drm/glint/glint_fbdev.c
@@ -0,0 +1,211 @@
+#include "drmP.h"
+#include "drm.h"
+#include "drm_fb_helper.h"
+
+#include <linux/fb.h>
+
+#include "glint.h"
+#include "glint_drv.h"
+
+struct glint_fbdev {
+	struct drm_fb_helper helper;
+	struct glint_framebuffer gfb;
+	struct list_head fbdev_list;
+	struct glint_device *gdev;
+};
+
+static struct fb_ops glintfb_ops = {
+	.owner = THIS_MODULE,
+	.fb_check_var = drm_fb_helper_check_var,
+	.fb_set_par = drm_fb_helper_set_par,
+	.fb_fillrect = cfb_fillrect,
+	.fb_copyarea = cfb_copyarea,
+	.fb_imageblit = cfb_imageblit,
+	.fb_pan_display = drm_fb_helper_pan_display,
+	.fb_blank = drm_fb_helper_blank,
+	.fb_setcmap = drm_fb_helper_setcmap,
+};
+
+static int glintfb_create(struct glint_fbdev *gfbdev,
+			  struct drm_fb_helper_surface_size *sizes)
+{
+	struct glint_device *gdev = gfbdev->gdev;
+	struct fb_info *info;
+	struct drm_framebuffer *fb;
+	struct drm_map_list *r_list, *list_t;
+	struct drm_local_map *map = NULL;
+	struct drm_mode_fb_cmd mode_cmd;
+	struct device *device = &gdev->pdev->dev;
+	int ret;
+
+	mode_cmd.width = sizes->surface_width;
+	mode_cmd.height = sizes->surface_height;
+	mode_cmd.bpp = sizes->surface_bpp;
+	mode_cmd.depth = sizes->surface_depth;
+	mode_cmd.pitch = mode_cmd.width * ((mode_cmd.bpp + 7) / 8);
+
+	info = framebuffer_alloc(0, device);
+	if (info == NULL)
+		return -ENOMEM;
+
+	info->par = gfbdev;
+
+	ret = glint_framebuffer_init(gdev->ddev, &gfbdev->gfb, &mode_cmd);
+	if (ret)
+		return ret;
+
+	fb = &gfbdev->gfb.base;
+	if (!fb) {
+		GLINT_INFO("fb is NULL\n");
+	}
+
+	/* setup helper */
+	gfbdev->helper.fb = fb;
+	gfbdev->helper.fbdev = info;
+
+	strcpy(info->fix.id, "glintdrmfb");
+
+	drm_fb_helper_fill_fix(info, fb->pitch, fb->depth);
+
+	info->flags = FBINFO_DEFAULT;
+	info->fbops = &glintfb_ops;
+
+	drm_fb_helper_fill_var(info, &gfbdev->helper, sizes->fb_width, sizes->fb_height);
+
+	/* setup aperture base/size for vesafb takeover */
+	info->apertures = alloc_apertures(1);
+	if (!info->apertures) {
+		ret = -ENOMEM;
+		goto out_iounmap;
+	}
+	info->apertures->ranges[0].base = gdev->ddev->mode_config.fb_base;
+	info->apertures->ranges[0].size = gdev->mc.vram_size;
+
+	list_for_each_entry_safe(r_list, list_t, &gdev->ddev->maplist, head) {
+		map = r_list->map;
+		if (map->type == _DRM_FRAME_BUFFER) {
+			map->handle = ioremap_nocache(map->offset, map->size);
+			if (!map->handle) {
+				GLINT_ERROR("fb: can't remap framebuffer\n");
+				return -1;
+			}
+			break;
+		}
+	}
+
+	info->fix.smem_start = map->offset;
+	info->fix.smem_len = map->size;
+	if (!info->fix.smem_len) {
+		GLINT_ERROR("%s: can't count memory\n", info->fix.id);
+		goto out_iounmap;
+	}
+	info->screen_base = map->handle;
+	if (!info->screen_base) {
+		GLINT_ERROR("%s: can't remap framebuffer\n", info->fix.id);
+		goto out_iounmap;
+	}
+
+	info->fix.mmio_start = 0;
+	info->fix.mmio_len = 0;
+
+	ret = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (ret) {
+		GLINT_ERROR("%s: can't allocate color map\n", info->fix.id);
+		ret = -ENOMEM;
+		goto out_iounmap;
+	}
+
+	DRM_INFO("fb mappable at 0x%lX\n",  info->fix.smem_start);
+	DRM_INFO("vram aper at 0x%lX\n",  (unsigned long)info->fix.smem_start);
+	DRM_INFO("size %lu\n", (unsigned long)info->fix.smem_len);
+	DRM_INFO("fb depth is %d\n", fb->depth);
+	DRM_INFO("   pitch is %d\n", fb->pitch);
+
+	return 0;
+out_iounmap:
+	iounmap(map->handle);
+	return ret;
+}
+
+static int glint_fb_find_or_create_single(struct drm_fb_helper *helper,
+					  struct drm_fb_helper_surface_size *sizes)
+{
+	struct glint_fbdev *gfbdev = (struct glint_fbdev *)helper;
+	int new_fb = 0;
+	int ret;
+
+	if (!helper->fb) {
+		ret = glintfb_create(gfbdev, sizes);
+		if (ret)
+			return ret;
+		new_fb = 1;
+	}
+	return new_fb;
+}
+
+static int glint_fbdev_destroy(struct drm_device *dev, struct glint_fbdev *gfbdev)
+{
+	struct fb_info *info;
+	struct glint_framebuffer *gfb = &gfbdev->gfb;
+
+	if (gfbdev->helper.fbdev) {
+		info = gfbdev->helper.fbdev;
+
+		unregister_framebuffer(info);
+		if (info->cmap.len)
+			fb_dealloc_cmap(&info->cmap);
+		framebuffer_release(info);
+	}
+
+	drm_fb_helper_fini(&gfbdev->helper);
+	drm_framebuffer_cleanup(&gfb->base);
+
+	return 0;
+}
+
+static struct drm_fb_helper_funcs glint_fb_helper_funcs = {
+	.gamma_set = glint_crtc_fb_gamma_set,
+	.gamma_get = glint_crtc_fb_gamma_get,
+	.fb_probe = glint_fb_find_or_create_single,
+};
+
+int glint_fbdev_init(struct glint_device *gdev)
+{
+	struct glint_fbdev *gfbdev;
+	int bpp_sel = 32;
+	int ret;
+
+	/* select 8 bpp console on <= 32 MB cards */
+	if (gdev->mc.vram_size <= (32 * MB))
+		bpp_sel = 8;
+
+	gfbdev = kzalloc(sizeof(struct glint_fbdev), GFP_KERNEL);
+	if (!gfbdev)
+		return -ENOMEM;
+
+	gfbdev->gdev = gdev;
+	gdev->mode_info.gfbdev = gfbdev;
+	gfbdev->helper.funcs = &glint_fb_helper_funcs;
+
+	ret = drm_fb_helper_init(gdev->ddev, &gfbdev->helper,
+				 gdev->num_crtc,
+				 GLINTFB_CONN_LIMIT);
+	if (ret) {
+		kfree(gfbdev);
+		return ret;
+	}
+	drm_fb_helper_single_add_all_connectors(&gfbdev->helper);
+	drm_fb_helper_initial_config(&gfbdev->helper, bpp_sel);
+
+	return 0;
+}
+
+void glint_fbdev_fini(struct glint_device *gdev)
+{
+	if (!gdev->mode_info.gfbdev)
+		return;
+
+	glint_fbdev_destroy(gdev->ddev, gdev->mode_info.gfbdev);
+	kfree(gdev->mode_info.gfbdev);
+	gdev->mode_info.gfbdev = NULL;
+}
diff --git a/drivers/gpu/drm/glint/glint_framebuffer.c b/drivers/gpu/drm/glint/glint_framebuffer.c
new file mode 100644
index 0000000..e6d58ca
--- /dev/null
+++ b/drivers/gpu/drm/glint/glint_framebuffer.c
@@ -0,0 +1,37 @@
+#include "drmP.h"
+#include "drm.h"
+#include "drm_crtc_helper.h"
+
+#include "glint.h"
+#include "glint_drv.h"
+
+static void glint_user_framebuffer_destroy(struct drm_framebuffer *fb)
+{
+	drm_framebuffer_cleanup(fb);
+}
+
+static int glint_user_framebuffer_create_handle(struct drm_framebuffer *fb,
+						struct drm_file *file_priv,
+						unsigned int *handle)
+{
+	return 0;
+}
+
+static const struct drm_framebuffer_funcs glint_fb_funcs = {
+	.destroy = glint_user_framebuffer_destroy,
+	.create_handle = glint_user_framebuffer_create_handle,
+};
+
+int glint_framebuffer_init(struct drm_device *dev,
+			   struct glint_framebuffer *gfb,
+			   struct drm_mode_fb_cmd *mode_cmd)
+{
+	int ret = drm_framebuffer_init(dev, &gfb->base, &glint_fb_funcs);
+	if (ret) {
+		GLINT_ERROR("drm_framebuffer_init failed: %d\n", ret);
+		return ret;
+	}
+	drm_helper_mode_fill_fb_struct(&gfb->base, mode_cmd);
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/glint/glint_mode.h b/drivers/gpu/drm/glint/glint_mode.h
index d0a2cc6..c6cbf00 100644
--- a/drivers/gpu/drm/glint/glint_mode.h
+++ b/drivers/gpu/drm/glint/glint_mode.h
@@ -11,6 +11,7 @@
 
 #define to_glint_crtc(x) container_of(x, struct glint_crtc, base)
 #define to_glint_encoder(x) container_of(x, struct glint_encoder, base)
+#define to_glint_framebuffer(x) container_of(x, struct glint_framebuffer, base)
 
 struct glint_crtc {
 	struct drm_crtc			base;
@@ -22,7 +23,9 @@
 
 struct glint_mode_info {
 	bool				mode_config_initialized;
-	struct glint_crtc		*crtcs[2]; /* FIXME: how many CRTCs? */
+	struct glint_crtc		*crtcs[1]; /* FIXME: how many CRTCs? */
+	/* pointer to fbdev info structure */
+	struct glint_fbdev		*gfbdev;
 };
 
 struct glint_encoder {
@@ -34,4 +37,8 @@
 	struct drm_connector		base;
 };
 
+struct glint_framebuffer {
+	struct drm_framebuffer		base;
+};
+
 #endif				/* __GLINT_MODE_H__ */
diff --git a/drivers/gpu/drm/glint/glint_ttm.c b/drivers/gpu/drm/glint/glint_ttm.c
new file mode 100644
index 0000000..96a0396
--- /dev/null
+++ b/drivers/gpu/drm/glint/glint_ttm.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2010 James Simmons
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+
+#include <ttm/ttm_bo_api.h>
+#include <ttm/ttm_bo_driver.h>
+#include <ttm/ttm_placement.h>
+#include <ttm/ttm_module.h>
+#include <ttm/ttm_page_alloc.h>
+
+#include "glint.h"
+
+static struct glint_device *glint_get_gdev(struct ttm_bo_device *bdev)
+{
+	struct glint_mman *mman;
+	struct glint_device *gdev;
+
+	mman = container_of(bdev, struct glint_mman, bdev);
+	gdev = container_of(mman, struct glint_device, mman);
+	return gdev;
+}
+
+static struct ttm_backend *
+glint_bo_create_ttm_backend_entry(struct ttm_bo_device *bdev)
+{
+	return NULL;
+}
+
+static int
+glint_bo_invalidate_caches(struct ttm_bo_device *bdev, uint32_t flags)
+{
+	return 0;
+}
+
+static int
+glint_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
+                         struct ttm_mem_type_manager *man)
+{
+	struct glint_device *gdev = glint_get_gdev(bdev);
+
+	switch (type) {
+	case TTM_PL_SYSTEM:
+		/* System memory */
+		man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
+		man->available_caching = TTM_PL_MASK_CACHING;
+		man->default_caching = TTM_PL_FLAG_CACHED;
+		break;
+	case TTM_PL_VRAM:
+		man->flags = TTM_MEMTYPE_FLAG_FIXED |
+			     TTM_MEMTYPE_FLAG_MAPPABLE;
+		man->available_caching = TTM_PL_FLAG_UNCACHED |
+					 TTM_PL_FLAG_WC;
+		man->default_caching = TTM_PL_FLAG_WC;
+		man->gpu_offset = gdev->mc.vram_base;
+		break;
+	default:
+		DRM_ERROR("Unsupported memory type %u\n", (unsigned)type);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static void
+glint_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl)
+{
+}
+
+static int
+glint_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr,
+		bool no_wait_reserve, bool no_wait_gpu,
+		struct ttm_mem_reg *new_mem)
+{
+	return 0;
+}
+
+static int
+glint_bo_verify_access(struct ttm_buffer_object *bo, struct file *filp)
+{
+	return 0;
+}
+
+static int
+glint_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
+{
+	return 0;
+}
+
+static void
+glint_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
+{
+}
+
+static int
+glint_ttm_fault_reserve_notify(struct ttm_buffer_object *bo)
+{
+	return 0;
+}
+
+struct ttm_bo_driver glint_bo_driver = {
+	.create_ttm_backend_entry = glint_bo_create_ttm_backend_entry,
+	.invalidate_caches = glint_bo_invalidate_caches,
+	.init_mem_type = glint_bo_init_mem_type,
+	.evict_flags = glint_bo_evict_flags,
+	.move = glint_bo_move,
+	.verify_access = glint_bo_verify_access,
+	.fault_reserve_notify = &glint_ttm_fault_reserve_notify,
+	.io_mem_reserve = &glint_ttm_io_mem_reserve,
+	.io_mem_free = &glint_ttm_io_mem_free,
+};
diff --git a/drivers/gpu/drm/glint/init_ttm.c b/drivers/gpu/drm/glint/init_ttm.c
new file mode 100644
index 0000000..0b35382
--- /dev/null
+++ b/drivers/gpu/drm/glint/init_ttm.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2010 James Simmons
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+
+#include "glint.h"
+
+#include <ttm/ttm_bo_api.h>
+#include <ttm/ttm_bo_driver.h>
+#include <ttm/ttm_placement.h>
+#include <ttm/ttm_module.h>
+#include <ttm/ttm_page_alloc.h>
+
+static int
+generic_ttm_mem_global_init(struct ttm_global_reference *ref)
+{
+	return ttm_mem_global_init(ref->object);
+}
+
+static void
+generic_ttm_mem_global_release(struct ttm_global_reference *ref)
+{
+	ttm_mem_global_release(ref->object);
+}
+
+void
+generic_ttm_global_release(struct glint_mman *ttm)
+{
+	if (ttm->mem_global_ref.release == NULL)
+		return;
+
+	ttm_global_item_unref(&ttm->bo_global_ref.ref);
+	ttm_global_item_unref(&ttm->mem_global_ref);
+	ttm->mem_global_ref.release = NULL;
+}
+
+int
+generic_ttm_global_init(struct glint_mman *ttm)
+{
+	struct ttm_global_reference *global_ref;
+	int r;
+
+	global_ref = &ttm->mem_global_ref;
+	global_ref->global_type = TTM_GLOBAL_TTM_MEM;
+	global_ref->size = sizeof(struct ttm_mem_global);
+	global_ref->init = &generic_ttm_mem_global_init;
+	global_ref->release = &generic_ttm_mem_global_release;
+	r = ttm_global_item_ref(global_ref);
+	if (r != 0) {
+		DRM_ERROR("Failed setting up TTM memory accounting "
+			"subsystem.\n");
+		return r;
+	}
+
+	ttm->bo_global_ref.mem_glob = ttm->mem_global_ref.object;
+	global_ref = &ttm->bo_global_ref.ref;
+	global_ref->global_type = TTM_GLOBAL_TTM_BO;
+	global_ref->size = sizeof(struct ttm_bo_global);
+	global_ref->init = &ttm_bo_global_init;
+	global_ref->release = &ttm_bo_global_release;
+	r = ttm_global_item_ref(global_ref);
+	if (r != 0) {
+		DRM_ERROR("Failed setting up TTM BO subsystem.\n");
+		ttm_global_item_unref(&ttm->mem_global_ref);
+		return r;
+	}
+
+	return 0;
+}